Java对象diff实用程序

时间:2012-08-29 10:31:34

标签: java diff

我正在寻找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'。

收集对象可能会变得更加棘手......

6 个答案:

答案 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){}
    }
}