是否有一个Java库可以;“差别”;两个物体?
是否有一个Java实用程序库类似于Unix程序diff,但用于对象?我正在寻找能够比较相同类型的两个对象并生成表示它们之间差异的数据结构(并且能够递归地比较实例变量的差异)的东西。我正在寻找文本差异的Java实现。我也在寻找如何使用反射来实现这一点的帮助 我维护的应用程序有一个脆弱的功能实现,它有一些糟糕的设计选择,需要重写,但是如果我们可以使用现成的东西,它会更好 下面是我正在寻找的一个例子:是否有一个Java库可以;“差别”;两个物体?,java,diff,Java,Diff,是否有一个Java实用程序库类似于Unix程序diff,但用于对象?我正在寻找能够比较相同类型的两个对象并生成表示它们之间差异的数据结构(并且能够递归地比较实例变量的差异)的东西。我正在寻找文本差异的Java实现。我也在寻找如何使用反射来实现这一点的帮助 我维护的应用程序有一个脆弱的功能实现,它有一些糟糕的设计选择,需要重写,但是如果我们可以使用现成的东西,它会更好 下面是我正在寻找的一个例子: SomeClass a = new SomeClass(); SomeClass b = new S
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成为一棵树是最自然的,但如果代码可靠,我不会挑剔。也许这会有所帮助,取决于您在哪里使用此代码,它可能有用或有问题。测试了这段代码
/**
* @param firstInstance
* @param secondInstance
*/
protected static void findMatchingValues(SomeClass firstInstance,
SomeClass secondInstance) {
try {
Class firstClass = firstInstance.getClass();
Method[] firstClassMethodsArr = firstClass.getMethods();
Class secondClass = firstInstance.getClass();
Method[] secondClassMethodsArr = secondClass.getMethods();
for (int i = 0; i < firstClassMethodsArr.length; i++) {
Method firstClassMethod = firstClassMethodsArr[i];
// target getter methods.
if(firstClassMethod.getName().startsWith("get")
&& ((firstClassMethod.getParameterTypes()).length == 0)
&& (!(firstClassMethod.getName().equals("getClass")))
){
Object firstValue;
firstValue = firstClassMethod.invoke(firstInstance, null);
logger.info(" Value "+firstValue+" Method "+firstClassMethod.getName());
for (int j = 0; j < secondClassMethodsArr.length; j++) {
Method secondClassMethod = secondClassMethodsArr[j];
if(secondClassMethod.getName().equals(firstClassMethod.getName())){
Object secondValue = secondClassMethod.invoke(secondInstance, null);
if(firstValue.equals(secondValue)){
logger.info(" Values do match! ");
}
}
}
}
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
/**
*@param firstInstance
*@param secondInstance
*/
受保护的静态void findMatchingValues(SomeClass firstInstance,
SomeClass(第二个实例){
试一试{
Class firstClass=firstInstance.getClass();
方法[]firstClassMethodsArr=firstClass.getMethods();
Class secondClass=firstInstance.getClass();
方法[]secondClassMethodsArr=secondClass.getMethods();
for(int i=0;i
一种更简单的方法是使用apache commons库来快速判断两个对象是否不同
BeanComparator lastNameComparator = new BeanComparator("lname");
logger.info(" Match "+bc.compare(firstInstance, secondInstance));
可能有点晚了,但我和你处于同样的情况,最终为你的用例创建了自己的库。因为我被迫自己想出一个解决方案,所以我决定在Github上发布它,以省去其他人的辛苦工作。你可以在这里找到它: ---编辑--- 下面是一个基于OPs代码的使用示例:
SomeClass a = new SomeClass();
SomeClass b = new SomeClass();
a.setProp1("A");
a.setProp2("X");
b.setProp1("B");
b.setProp2("X");
DiffNode diff = ObjectDifferBuilder.buildDefault().compare(a, b);
assert diff.hasChanges();
assert diff.childCount() == 1;
assert diff.getChild('prop1').getState() == DiffNode.State.CHANGED;
是一个库,它可以很好地满足您的需要:它有一些方法,比如compare(objectleftgraph,objectrightgraph)返回Diff对象。Diff包含更改列表(ReferenceChange、ValueChange、PropertyChange),例如
它可以处理图形中的循环
此外,您还可以获取任何图形对象的快照。Javers有用于快照的JSON序列化程序和反序列化程序,以及更改,所以您可以轻松地将它们保存在数据库中。有了这个库,你可以很容易地实现一个审计模块。所有的Javers库都只支持Java 7,我遇到了这样的情况,因为我想将它用于Java 6项目,所以我碰巧取了源代码,并更改了适用于Java 6的github代码 Jar链接: 我只将Java 7支持的“”固有强制转换转换更改为Java 6支持
我不能保证所有的功能都能正常工作,因为我已经对一些不必要的代码进行了注释。它适用于所有自定义对象比较。是的,该库有一个GraphComparator类,可以比较两个Java对象图。它以增量列表的形式返回差异。GraphComparator还允许您合并(应用)三角洲。这段代码只依赖于JDK,没有其他库。您还可以看看Apache的解决方案。 由于它是commons-lang的一部分,大多数项目的类路径上已经有了它 检查特定字段的差异:
使用反射检查差异:
检查这个,可能的重复不是“如何测试复杂对象图的相等性?”的重复,我要找的是一个库,而不是如何做的建议。此外,我对delta感兴趣,而不是它们是否相等。看看哪个有图形比较工具。此类将生成对象图之间的增量列表。此外,它还可以将增量合并(应用)到图形。实际上,它是List=GraphComparator(rootA,rootB)。还有GraphComparator.applyDelta(rootB,List)。我知道你不想使用反射,但这绝对是实现这样的东西的最简单/简单的方法,它对我不起作用,因为我需要知道发生了什么变化,而不仅仅是某个地方发生了变化。谢谢,但是我们已经有了使用反射来遍历对象图的代码,它列出了更改。这个问题不是关于如何做到这一点,而是关于如何避免重新发明轮子。如果
given:
DummyUser user = dummyUser("id").withSex(FEMALE).build();
DummyUser user2 = dummyUser("id").withSex(MALE).build();
Javers javers = JaversTestBuilder.newInstance()
when:
Diff diff = javers.compare(user, user2)
then:
diff.changes.size() == 1
ValueChange change = diff.changes[0]
change.leftValue == FEMALE
change.rightValue == MALE