Jeśli dobrze rozumiem, próbujesz obliczyć symmetric difference pomiędzy zestawami wejściowymi dwóch map.
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);
Biorąc pod uwagę dziwne zachowanie, o którym wspomniałeś, przyjrzyjmy się powyższemu zachowaniu kodu. Na przykład, jeśli weźmiemy przykład liczbowy z wyżej podanym linku:
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);
Po obliczyć różnicę, jak pokazano, wyjście:
System.out.println(Arrays.deepToString(diff12.toArray()));
daje:
[e=5, c=3, b=2]
który jest poprawny wynik. Ale, jeśli robimy to tak:
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));
ten sam algorytm daje następujący wynik:
[e=5, a=1, d=4, d=4, b=2, a=1, c=3]
co nie jest poprawne (i może być opisana jako niewygodne :))
W pierwszy przykład mapa jest wypełniona wartościami int, które automatycznie są boxed na wartości całkowite.
ma własną implementację metod equals i hashCode.
Klasa CustomInteger nie implementuje tych metod, dzięki czemu są one inherits z wszechobecnego .
Doc API dla removeAll method z Set interface mówi co następuje:
Usuwa z tego zbioru wszystkich jego elementów, które są zawarte w określonej kolekcji (opcjonalnie operacja). Jeśli określona kolekcja jest również zbiorem, ta operacja efektywnie modyfikuje ten zbiór, tak aby jego wartość stanowiła asymetryczną różnicę zestawu dwóch zestawów.
Aby określić, które elementy znajdują się w obu kolekcjach, metoda removeAll używa metody równości elementu kolekcji.
I haczyk: całkowita na równe sposób powraca do sytuacji, gdy obie wartości numeryczne są takie same, podczas gdy obiektu jest równy sposób powraca prawdą tylko wtedy, gdy obiekt sam np :
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
Jeśli to wciąż nieco rozmyty Sugeruję czytania następujące tutoriale:
Dzięki. Myślałem o guava, ale do tego potrzebna jest nowa biblioteka w projekcie, nie rób tego. – user710818
@ user710818 Nie żałowałbyś tego - jest to świetna biblioteka – vitaly
@ user710818 Powinieneś użyć tego w swoim projekcie – Koerr