4

我正在寻找 Java 中的通用实用程序,它可以帮助我为两个对象(相同类型)创建差异报告。

例如,如果我的类结构是:

class A {
  int p1;
  string p2;
  B b1;
}

class B {
 float p3;
}

我想要一个 b/w 两个 A 类型对象(例如 a1 和 a2)的报告,如下所示:a1 与 a2

p1 : 'remove'
p2 : 'change'
b1.p3: 'add'

其中,如果属性在第二个对象中为 null,则设置“remove”,如果属性存在但具有不同的值,则设置“change”,如果属性在第一个对象中为 null,则设置“add”。

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

4

6 回答 6

11

我为此创建了一个库:https ://github.com/SQiShER/java-object-diff

它构建了比较对象的树结构,并允许您通过访问者模式遍历节点。查看入门页面,查看一些示例。它适用于几乎任何类型的对象,并且可以处理任意数量的嵌套级别。我什至设法基于它构建了一个自动对象合并。

这种对象图的打印版本如下所示:

Property at path '/contacts/item[Walter White]/middleName' has been added => [ Hartwell ]
Property at path '/contacts/item[Jesse Pinkman]/middleName' has been added => [ Bruce ]

我自己使用它,它就像一个魅力。希望能帮助到你!

我不知道您的对象有多复杂,但是通过反射手动进行操作很快就会失控。尤其是当涉及地图和收藏时。

于 2012-08-29T11:42:18.107 回答
8

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 中实现了存储。

于 2014-10-31T19:32:30.253 回答
1

看看我制作的这个库。也许它对某人有用(支持差异/补丁/与任意深度对象图和集合/映射/数组比较)......

使用起来应该很简单:

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));

这是 github 存储库的链接。(https://github.com/bojanv55/entity-sync-utils)

于 2015-12-28T22:38:20.693 回答
0

使用 apache 创建 2 个对象的 sting 表示ToStringBuilder。然后比较字符串。

看看这个讨论:How to perform string Diffs in Java?

它包含对在 java 中执行文本差异的库的引用。

于 2012-08-29T11:16:09.953 回答
0

我怀疑是否有通用实用程序可以做到这一点。

但这似乎并不难使用 java 反射 API 编写。

您可以使用枚举类的字段

myClass.getFields();

所以你只需要进行深入的比较。

于 2012-08-29T10:34:21.740 回答
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){}
    }
}
于 2012-08-29T11:34:51.557 回答