4

(同じタイプの) 2 つのオブジェクトの差分レポートを作成するのに役立つ Java の汎用ユーティリティを探しています。

たとえば、私のクラス構造が次の場合:

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

class B {
 float p3;
}

次のように、タイプ A の 2 つのオブジェクト (たとえば、a1 と a2) を含むレポートが必要です: a1 と a2

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

ここで、プロパティが 2 番目のオブジェクトで null の場合は「削除」が設定され、プロパティが存在するが値が異なる場合は「変更」が設定され、最初のオブジェクトでプロパティが null の場合は「追加」が設定されます。

コレクションオブジェクトの場合、よりタフ/トリッキーになる可能性があります...

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

Javarsは、必要なことを正確に実行するライブラリです。

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

グラフのサイクルを処理できます。

さらに、任意のグラフ オブジェクトのスナップショットを取得できます。Javars には、スナップショットを作成するための 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

それを行うための一般的なユーティリティがあるとは思えません。

しかし、それは Java リフレクション API を使用して記述するのは難しくないようです。

を使用してクラスのフィールドを列挙できます

myClass.getFields();

したがって、徹底的に比較する必要があります。

于 2012-08-29T10:34:21.740 に答える
0

リフレクション API を使用してそれを実現できます。

私は完全なコードを与えていません。しかし、これはあなたが始めることができる1つの方法です。

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 に答える
0

apache を使用して 2 つのオブジェクトの文字列表現を作成しますToStringBuilder。次に、文字列を比較します。

この議論を見てください: How to perform string Diffs in Java?

Java でテキスト diff を実行するライブラリへの参照が含まれています。

于 2012-08-29T11:16:09.953 に答える