是否有一个类似于 Unix 程序 diff 的 Java 实用程序库,但是针对对象?我正在寻找可以比较相同类型的两个对象并生成表示它们之间差异的数据结构(并且可以递归比较实例变量中的差异)的东西。我不是寻找文本差异的Java 实现。我也不寻求有关如何使用反射来执行此操作的帮助。
我正在维护的应用程序对此功能的实现很脆弱,有一些糟糕的设计选择,需要重写,但如果我们可以使用现成的东西,那就更好了。
这是我正在寻找的此类事物的示例:
SomeClass a = new SomeClass();
SomeClass b = new SomeClass();
a.setProp1("A");
a.setProp2("X");
b.setProp1("B");
b.setProp2("X");
DiffDataStructure diff = OffTheShelfUtility.diff(a, b); // magical recursive comparison happens here
比较后,实用程序会告诉我两个对象之间的“prop1”不同,而“prop2”相同。我认为 DiffDataStructure 成为一棵树是最自然的,但如果代码可靠的话我不会挑剔。
Is there a Java utility library that is analogous to the Unix program diff, but for Objects? I'm looking for something that can compare two objects of the same type and generate a data structure that represents the differences between them (and can recursively compare differences in instance variables). I'm not looking for a Java implementation of a text diff. I'm also not looking for help with how to use reflection to do this.
The application I'm maintaining has a fragile implementation of this functionality that had some poor design choices and that needs to be rewritten, but it would be even better if we could use something off the shelf.
Here's an example of the kind of thing I'm looking for:
SomeClass a = new SomeClass();
SomeClass b = new SomeClass();
a.setProp1("A");
a.setProp2("X");
b.setProp1("B");
b.setProp2("X");
DiffDataStructure diff = OffTheShelfUtility.diff(a, b); // magical recursive comparison happens here
After comparison, the utility would tell me that "prop1" is different between the two objects and "prop2" is the same. I think it's most natural for DiffDataStructure to be a tree, but I'm not going to be picky if the code is reliable.
发布评论
评论(8)
可能有点晚了,但我和你的情况一样,最终为你的用例创建了我自己的库。由于我被迫自己想出一个解决方案,所以我决定将其发布在 Github 上,以免其他人辛苦工作。您可以在这里找到它:https://github.com/SQiShER/java-object-diff
--- 编辑 ---
这是一个基于OP代码的使用示例:
Might be a little late, but I was in the same situation like you and ended up creating my own library for exactly your use-case. Since I was forced to come up with a solution myself, I decided to release it on Github, to spare others the hard work. You can find it here: https://github.com/SQiShER/java-object-diff
--- Edit ---
Here is a little usage example based on the OPs code:
http://javers.org 是一个库,它完全可以满足您的需求:具有诸如compare(Object leftGraph, Object rightGraph)之类的方法,返回 Diff 对象。 Diff 包含更改列表(ReferenceChange、ValueChange、PropertyChange),例如
它可以处理图形中的循环。
此外,您还可以获得任何图形对象的快照。 Javers 具有用于快照和更改的 JSON 序列化器和反序列化器,以便您可以轻松地将它们保存在数据库中。通过这个库,您可以轻松实现审计模块。
http://javers.org is library that does exacly what you need: has methods like compare(Object leftGraph, Object rightGraph) returning the Diff object. Diff contains a list of changes (ReferenceChange, ValueChange, PropertyChange) e.g.
It can handle cycles in graphs.
In addition you can get Snapshot of any graph object. Javers has JSON serializers and deserializers to snapshot, and changes so you can easily save them in database. With this library you can easily implement a module for auditing.
您还可以看看 Apache 的解决方案。
大多数项目已经将它放在类路径中,因为它是 commons-lang 的一部分。
检查特定字段的差异:
http:// /commons.apache.org/proper/commons-lang/javadocs/api-3.9/org/apache/commons/lang3/builder/DiffBuilder.html
使用检查差异反思:
http:// /commons.apache.org/proper/commons-lang/javadocs/api-3.9/org/apache/commons/lang3/builder/ReflectionDiffBuilder.html
You could also take a look at the solution from Apache.
Most projects already have it on their classpath since its part of commons-lang.
Check difference for specific field(s):
http://commons.apache.org/proper/commons-lang/javadocs/api-3.9/org/apache/commons/lang3/builder/DiffBuilder.html
Check difference by using reflection:
http://commons.apache.org/proper/commons-lang/javadocs/api-3.9/org/apache/commons/lang3/builder/ReflectionDiffBuilder.html
所有 Javers 库仅支持 Java 7,我的情况是因为我希望将其用于 Java 6 项目,所以我碰巧获取了源代码并以适用于 Java 6 的方式进行了更改,下面是 github 代码。
https://github.com/sand3sh/javers-forJava6
Jar 链接:https://github.com/sand3sh/javers-forJava6/blob/master/build/javers-forjava6.jar
我只更改了 Java 7 支持的 '<>'对 Java 6 支持的固有强制转换
我不保证所有功能都能工作,因为我已经评论了一些不必要的代码,它适用于所有自定义对象比较。
All the Javers library has support to only Java 7, I was in a situation since I want this to be used for a Java 6 project so I happened to take the source and change in a way it works for Java 6 below is the github code.
https://github.com/sand3sh/javers-forJava6
Jar link: https://github.com/sand3sh/javers-forJava6/blob/master/build/javers-forjava6.jar
I have only changed the Java 7 supported '<>' inherent cast conversions to Java 6 support
I dont gurantee all the functionalities will work since I have commented few unnecessary code for me it works for all custom objects comparision.
深入比较对象所有属性的一个好方法是将它们转换为
java.util.Map
。完成后,java.util.Map#equals
将深入比较对象,工作就完成了!唯一的问题是将对象转换为 Map。一种方法是使用 org.codehaus.jackson.map.ObjectMapper 的反射。
因此,
com.google.common.collect.MapDifference
中存在一个工具来描述两个地图之间的差异。A good way to compare deeply all properties of an objects is to convert them to
java.util.Map
. Done that, thejava.util.Map#equals
will deeply compare the objects and the job is done !The only problem is to convert the object to a Map. One way to do it is to use reflexion with
org.codehaus.jackson.map.ObjectMapper
.Therefore, it exist a tool from
com.google.common.collect.MapDifference
which describe the defferences between the two maps.也许这会有所帮助,具体取决于您使用此代码的位置,它可能有用或有问题。测试了这段代码。
Maybe this will help, depending on where you use this code, it could be useful or problematic. Tested this code.
首先,我们必须将对象转换为地图:
然后将地图转换为展平地图:
最后调用 getDifferenceBetween2Maps 来获取差异:
使用示例:
Firstly we have to convert our objects to map:
after that convert the map to flatten map:
and finaly call getDifferenceBetween2Maps to get the differences:
using example :
快速告诉您两个对象是否不同的更简单方法是使用 apache commons 库
A simpler approach to quickly tell you if two objects are different would be is to use the apache commons library