我有两个复杂的对象。我想比较两个相似的对象结构并列出差异。我在所有论坛中搜索,没有正确的解决方案。
每个人都在建议反射方法。反射方法没有帮助我,我尝试了一下。我的对象结构太复杂了。
以下是我的对象结构。列表中包含的对象在其他列表中的顺序可能不同。一个列表可能有该对象,另一个对象可能没有该列表。
结构:
对象
-Field
-Field
-Field
列表
-对象
-object
-object
-列表
-object
-Field
-Field
-对象
-Field
-Field
-Field
-Field
-列表
-object
-Field
-Field
-对象
-Field
-Field
答案 0 :(得分:1)
我仍然建议您调查Java Reflection。参见Wikipedia。
例如,如果属性本身是对象,则可以使用Reflection进行递归调用,从而通过相同的方法输入它。
public void determineObjectStructure (Object o) {
Field[] fields = o.getClass().getDeclaredFields();
for (Field field : fields) {
// Check Type of field
// If not primitive -> determineObjectStructure()
// create Representation
}
}
然后,您可以手动创建一个包含以下内容的“复杂对象结构”表示形式:带有以下内容的列表:
levelInComplexObject |对象
然后,可以使用最终列表与从不同对象创建的列表进行比较,并且可以在不同组织级别上比较其结构。
答案 1 :(得分:0)
我同意您对复杂对象的反映方式会变得有些复杂。我也有类似的用例,其中需要比较两个对象,而且我的对象也非常复杂(太多不同类型的字段和关联链)。
因此,进行了过多的搜索,找到了很多解决方案,包括反射方法,JSON比较,但是我最喜欢Job的最有希望的框架是Javers。
一个简单的例子可能是:
@Test
public void shouldCompareTwoEntities() {
//given
Javers javers = JaversBuilder.javers()
.withListCompareAlgorithm(LEVENSHTEIN_DISTANCE)
.build();
Employee frodoOld = EmployeeBuilder.Employee("Frodo")
.withAge(40)
.withPosition("Townsman")
.withSalary(10_000)
.withPrimaryAddress(new Address("Shire"))
.withSkills("management")
.withSubordinates(new Employee("Sam"))
.build();
Employee frodoNew = EmployeeBuilder.Employee("Frodo")
.withAge(41)
.withPosition("Hero")
.withBoss(new Employee("Gandalf"))
.withPrimaryAddress(new Address("Mordor"))
.withSalary(12_000)
.withSkills("management", "agile coaching")
.withSubordinates(new Employee("Sméagol"), new Employee("Sam"))
.build();
//when
Diff diff = javers.compare(frodoOld, frodoNew);
//then
assertThat(diff.getChanges()).hasSize(9);
}
javers.compare(frodoOld, frodoNew)
接受两个对象并进行比较并报告差异。在您的情况下,对象具有列表,并且列表中的元素可以采用不同的顺序,在这种情况下,Javers
将它们报告为差异。如果要忽略元素的顺序,则在将对象馈送到Javers
之前,可以对列表进行排序,然后进行比较。
您可以看看JaVers Documentation
最简单的示例是:
Person pOld = new Person ();
pOld.setName("Foo"):
Person pNew = new Person ();
pNew.setName("Bar"):
Diff diff = javers.compare(pOld, pNew);
diff.getChanges()
将给出差异列表。
答案 2 :(得分:0)
ANTLR project是一组用于分析源代码的复杂工具。参见Wikipedia。
您编写了定义编程语言规则的语法。对于Java,这已经完成。您可以下载Java语言的开源语法.g4
文件。
您将此语法输入到ANTLR中。语法分析器可以识别源代码文件的单词,语法分析器可以识别源代码文件的短语和语句。
您编译这些生成的源文件。然后输入您的Java源文件。出现了抽象语法树,它是表示Java源代码内容的数据结构。您可以轻松地走到那棵树上,随身收集零件(类名,成员变量,方法,参数,局部变量等)。
通过使用ANTLR生成的更多源代码,走路树很容易。这段代码使用了Listener和Visitor模式,因此您可以仅覆盖感兴趣的部分的几种方法。
ANTLR是开源且免费的。
请参阅由ANTLR的主要创建者Terence Parr撰写的标题为The Definitive ANTLR 4 Reference的优秀指南和参考书。