Si lo entendí bien, está tratando de calcular symmetric difference entre los dos juegos de entradas de mapas.
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);
Teniendo en cuenta el comportamiento extraño que usted ha mencionado, vamos a echar un vistazo más de cerca el comportamiento de código de seguridad. Por ejemplo, si tomamos el ejemplo numérico desde el vínculo anterior:
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);
Después de calcular la diferencia como se muestra, la salida:
System.out.println(Arrays.deepToString(diff12.toArray()));
da:
[e=5, c=3, b=2]
cual es el resultado correcto Pero, si lo hacemos así:
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));
el mismo algoritmo da el siguiente resultado:
[e=5, a=1, d=4, d=4, b=2, a=1, c=3]
que no es correcta (y que podría describirse como incómoda :))
En el primer ejemplo que el mapa se llena con valores int que son automáticamente boxed a valores enteros.
The class Integer tiene su propia implementación de los métodos equals y hashCode.
La clase CustomInteger no implementa estos métodos por lo que inherits de la omnipresencia Object class.
El doc API para el removeAll method de la Set interface dice lo siguiente:
elimina de este conjunto de todos los elementos que están contenidos en la colección especificada (operación opcional). Si la colección especificada también es un conjunto, esta operación modifica efectivamente este conjunto de modo que su valor sea la diferencia del conjunto asimétrico de los dos conjuntos.
Con el fin de determinar qué elementos están contenidos en ambas colecciones, el método removeAll utiliza el método equals del elemento de colección.
Y ese es el problema: Entero de igual método devuelve true si los dos valores numéricos son los mismos, mientras que el Objeto de igual método devolverá verdadero sólo si es el objeto misma, por ejemplo, :
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
Si aún así es un poco difusa que sugieren fuertemente la lectura de los siguientes tutoriales:
Gracias. Pensé en la guayaba, pero para esto necesito introducir una nueva biblioteca en el proyecto, pero no hagas esto. – user710818
@ user710818 No se arrepentirá, es una gran biblioteca – vitaly
@ user710818 Debe usarla en su proyecto – Koerr