我正在寻找Java中的通用实用程序,它可以帮助我为两个对象(相同类型)创建差异报告。
例如,如果我的类结构是:
class A {
int p1;
string p2;
B b1;
}
class B {
float p3;
}
我想要一个报告b / w两个类型为A的对象(比如a1和a2),如下所示: a1 vs. a2
p1 : 'remove'
p2 : 'change'
b1.p3: 'add'
其中,如果属性在第二个对象中为null,则设置'remove',如果属性存在但是具有不同的值则为'change',如果第一个对象中的属性为null,则为'add'。
收集对象可能会变得更加棘手......
答案 0 :(得分:10)
我为此创建了一个库:https://github.com/SQiShER/java-object-diff
它构建了比较对象的树结构,并允许您通过访问者模式遍历节点。查看Getting Started页面,查看一些示例。它适用于几乎任何类型的对象,可以处理任意数量的嵌套级别。我甚至设法基于它构建一个自动对象合并。
此类对象图的打印版本如下所示:
Property at path '/contacts/item[Walter White]/middleName' has been added => [ Hartwell ]
Property at path '/contacts/item[Jesse Pinkman]/middleName' has been added => [ Bruce ]
我自己使用它,它就像一个魅力。希望它有所帮助!
我不知道您的对象有多复杂,但是通过反射手动完成它会很快失控。特别是当地图和收藏集参与其中时。
答案 1 :(得分:6)
Javers是一个可以满足您需求的库:
given:
DummyUser user = dummyUser("id").withSex(FEMALE).build();
DummyUser user2 = dummyUser("id").withSex(MALE).build();
Javers javers = JaversBuilder.javers().build()
when:
Diff diff = javers.compare(user, user2)
then:
diff.changes.size() == 1
ValueChange change = diff.changes[0]
change.leftValue == FEMALE
change.rightValue == MALE
它可以处理图表中的循环。
此外,您还可以获取任何图形对象的快照。 Javers有JSON序列化器和反序列化器来快照和更改,还在mongoDB中实现了存储。
答案 2 :(得分:1)
我怀疑有这样的通用实用程序。
但是使用java反射API编写似乎并不难。
您可以使用
枚举班级的字段myClass.getFields();
所以你只需进行深入的比较。
答案 3 :(得分:1)
看看我制作的这个库。也许它对某人有用(支持diff / patch /与任意深度对象图和集合/贴图/数组进行比较)......
使用起来应该很简单:
GrandChildEntity gce1 = new GrandChildEntity(1);
GrandChildEntity gce2 = new GrandChildEntity(2);
Diff diff = new Diff.Builder().build();
Patch patch = new Patch.Builder().build();
Compare compare = new Compare.Builder().build();
Element<Name, GrandChildEntity> diffElement = diff.diff(gce1, gce2);
GrandChildEntity patchedEntity = patch.patch(new GrandChildEntity(1), diffElement);
boolean areEqual = compare.compare(patchedEntity, new GrandChildEntity(2));
This is the link to github repo. (https://github.com/bojanv55/entity-sync-utils)
答案 4 :(得分:0)
使用apache ToStringBuilder
创建2个对象的sting表示。然后比较字符串。
看一下这个讨论:How to perform string Diffs in Java?
它包含对在java中执行文本差异的库的引用。
答案 5 :(得分:0)
您可以使用反射API来实现它。
我没有提供完整的代码。但这是你可以开始的一种方式。
class Testapp {
public static void main(String[] args) {
A a1 = new A();
A a2 = new A();
a1.b1.p3 = 1;
a1.p1 = 2;
a1.p2 = "Hi";
a2.b1.p3 = 1;
a2.p1 = 3;
a2.p2 = "Hi";
Compare c = new Compare<A>(a1, a2);
c.compare();
}
}
class A
{
int p1;
String p2;
B b1;
A() {
b1 = new B();
}
}
class B {
float p3;
}
class Compare<T extends Object> {
T a;
T b;
public Compare(T a, T b)
{
this.a = a;
this.b = b;
}
public void compare()
{
try
{
Field[] fields = a.getClass().getDeclaredFields();
for (Field field : fields) {
if(field.get(a)==field.get(b)){
//do something
}
}
}catch(Exception e){}
}
}