19

私は2つのマップを持っています:

Map<String, Object> map1;
Map<String, Object> map2;

これらのマップの違いを受け取る必要があります。この違いを受け取る方法は、apache utils である可能性がありますか? 今のところ、各マップのエントリ セットを取得する必要があるようで、diff1 = set1 - set2 および diff2 = set2-set1 が見つかりました。要約マップを作成した後 =diff1 + diff2 非常にぎこちなく見えます。別の方法は存在しますか?ありがとう。

4

7 に答える 7

44

グーグルグアバはどうですか?:

Maps.difference(map1,map2)
于 2012-10-04T06:52:40.870 に答える
22

大規模な Guava ライブラリの代わりに使用できる簡単なスニペットを次に示します。

public static <K, V> Map<K, V> mapDifference(Map<? extends K, ? extends V> left, Map<? extends K, ? extends V> right) {
    Map<K, V> difference = new HashMap<>();
    difference.putAll(left);
    difference.putAll(right);
    difference.entrySet().removeAll(right.entrySet());
    return difference;
}

動作例全体をチェックしてください

于 2014-07-17T21:53:51.883 に答える
7

私がよく理解していれば、2 つのマップ エントリ セット間の対称差を計算しようとしています。

Map<String, Object> map1;
Map<String, Object> map2;

Set<Entry<String, Object>> diff12 = new HashSet<Entry<String, Object>>(map1.entrySet());
Set<Entry<String, Object>> diff21 = new HashSet<Entry<String, Object>>(map2.entrySet());
Set<Entry<String, Object>> result;

diff12.removeAll(map2.entrySet());
diff21.removeAll(map1.entrySet());
diff12.addAll(diff21);

あなたが言及した厄介な動作を考慮して、上記のコードの動作を詳しく見てみましょう。たとえば、上記のリンクから数値例を取得すると、次のようになります。

Map<String, Object> map1 = new HashMap<String, Object>();
map1.put("a", 1);
map1.put("b", 2);
map1.put("c", 3);
map1.put("d", 4);

Map<String, Object> map2 = new HashMap<String, Object>();
map2.put("a", 1);    
map2.put("d", 4);
map2.put("e", 5);

示されているように差を計算すると、出力は次のようになります。

System.out.println(Arrays.deepToString(diff12.toArray()));

与えます:

[e=5, c=3, b=2]

これが正しい結果です。しかし、次のようにすると:

public class CustomInteger {
    public int val;

    public CustomInteger(int val) {
        this.val = val;
    }

    @Override
    public String toString() {
        return String.valueOf(val);
    }        
}   

map1.put("a", new CustomInteger(1));
map1.put("b", new CustomInteger(2));
map1.put("c", new CustomInteger(3));
map1.put("d", new CustomInteger(4));

map2.put("a", new CustomInteger(1));    
map2.put("d", new CustomInteger(4));
map2.put("e", new CustomInteger(5));

同じアルゴリズムで次の出力が得られます。

[e=5, a=1, d=4, d=4, b=2, a=1, c=3]

これは正しくありません (そして、ぎこちないと説明されるかもしれません :) )

最初の例では、マップは int 値で満たされ、自動的に Integer 値にボックス化されます。

クラス Integerには、 equalsおよびhashCodeメソッドの独自の実装があります。

クラス CustomInteger はこれらのメソッドを実装しないため、遍在するObject クラスから継承します。

Set インターフェイスのremoveAll メソッドのAPI ドキュメントには、次のように記載されています。

指定されたコレクションに含まれるすべての要素をこのセットから削除します (オプションの操作)。指定されたコレクションもセットである場合、この操作はこのセットを効果的に変更し、その値が 2 つのセットの非対称セットの差になるようにします。

両方のコレクションに含まれる要素を判別するために、removeAll メソッドはコレクション要素の equals メソッドを使用します。

それがキャッチです: Integer の equals メソッドは、2 つの数値が同じ場合に true を返しますが、Object の equals メソッドは、同じオブジェクトである場合にのみ true を返します。

Integer a = 1; //autoboxing
Integer b = new Integer(1);
Integer c = 2;

a.equals(b); //  true
a.equals(c); //  false

CustomInteger d = new CustomInteger(1);
CustomInteger e = new CustomInteger(1);
CustomInteger f = new CustomInteger(2);

d.equals(e); //false
d.equals(f) // false

d.val == e.val //true
d.val == f.val //false

それでも少しあいまいな場合は、次のチュートリアルを読むことを強くお勧めします。

于 2012-10-04T16:16:19.063 に答える
4
    Set<Entry<String, Object>> diff = new HashSet<Entry<String, Object>>((map1.entrySet()));
    diff.addAll(map2.entrySet());//Union
    Set<Entry<String, Object>> tmp = new HashSet<Entry<String, Object>>((map1.entrySet()));
    tmp.retainAll(map2.entrySet());//Intersection
    diff.removeAll(tmp);//Diff
于 2012-10-04T06:50:37.500 に答える
0

グアバのMapDifferenceを使用してみてください。

于 2012-10-04T06:54:10.840 に答える