有没有一个Java库,可以“差异”两个对象?
是否有一个类似于Unix程序差异的Java实用程序库,但是对于对象? 我正在寻找可以比较两个相同types的对象的东西,并生成一个表示它们之间差异的数据结构(并且可以recursion地比较实例variables中的差异)。 我不是在寻找一个文本差异的Java实现。 我也没有find如何使用reflection来做到这一点的帮助。
我正在维护的应用程序有一个脆弱的实现这个function,有一些糟糕的deviseselect,需要重写,但如果我们可以使用一些现成的东西会更好。
这是我正在寻找的东西的一个例子:
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是一棵树是最自然的,但如果代码是可靠的,我不会挑剔。
可能会有点晚,但是我和你一样处于相同的状况,最终创build了我自己的库,用于你的用例。 由于我自己不得不提出一个解决scheme,所以我决定在Github上释放它,以免其他人辛苦工作。 你可以在这里find它: https : //github.com/SQiShER/java-object-diff
— 编辑 —
以下是基于OP代码的一个小例子:
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;
http://javers.org是一个可以完全满足你需要的库:有像compare(Object leftGraph,Object rightGraph)这样的方法返回Diff对象。 差异包含一系列的变化(ReferenceChange,ValueChange,PropertyChange)例如
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
它可以处理graphics中的循环。
另外你可以得到任何graphics对象的快照。 Javers有JSON序列化器和反序列化器来进行快照,并进行更改,以便您可以轻松地将其保存在数据库中。 有了这个库,您可以轻松实现审计模块。
是的, java-util库有一个GraphComparator类来比较两个Java对象图。 它将返回差异作为增量列表。 GraphComparator也允许你合并(应用)增量。 这段代码只依赖于JDK,没有其他的库。
所有的Javer库都只支持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支持我不保证所有的function将工作,因为我已经评论了一些不必要的代码对我来说适用于所有自定义对象的比较。
也许这将有所帮助,这取决于你使用这个代码的地方,它可能是有用的或有问题的。 testing了这个代码。
/** * @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(); } }
一个简单的方法来快速告诉你,如果两个对象是不同的将是使用Apache公共库
BeanComparator lastNameComparator = new BeanComparator("lname"); logger.info(" Match "+bc.compare(firstInstance, secondInstance));