recorrer example entre ejemplo diferencia java collections map set set-difference

example - ¿Cómo recibir la diferencia de mapas en Java?



recorrer hashmap java foreach (7)

Hay una API MapDifference de Google Collections Library que expone métodos como:

boolean areEqual()

Devuelve verdadero si no hay diferencias entre los dos mapas; es decir, si los mapas son iguales.

Map<K,MapDifference.ValueDifference<V>> entriesDiffering()

Devuelve un mapa no modificable que describe las claves que aparecen en ambos mapas, pero con diferentes valores.

Map<K,V> entriesInCommon()

Devuelve un mapa no modificable que contiene las entradas que aparecen en ambos mapas; es decir, la intersección de los dos mapas.

Tengo dos mapas:

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

Necesito recibir la diferencia entre estos mapas. ¿Existiría apache utiliza cómo recibir esta diferencia? Por ahora parece necesario tomar el conjunto de entrada de cada mapa y se encuentran diff1 = set1 - set2 y diff2 = set2 - set1. Después de crear un mapa resumen = diff1 + diff2 Parece muy incómodo. ¿Existe otra forma? Gracias.



Si lo entendí bien, está tratando de calcular la diferencia simétrica entre los dos conjuntos de entrada 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 incómodo que mencionó, echemos un vistazo más de cerca al comportamiento del código anterior. Por ejemplo, si tomamos el ejemplo numérico del enlace dado arriba:

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 proporciona el siguiente resultado:

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

que no es correcto (y podría describirse como incómodo :))

En el primer ejemplo, el mapa está lleno de valores int que se encapsulan automáticamente en valores enteros.

La clase Integer tiene su propia implementación de métodos equals y hashCode .

La clase CustomInteger no implementa estos métodos, por lo que los hereda de la clase Objeto omnipresente.

El documento de API para el método removeAll de la interfaz Set dice lo siguiente:

Elimina de este conjunto todos sus 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.

Para determinar qué elementos están contenidos en ambas colecciones, el método removeAll usa el método equals del elemento de colección.

Y ese es el truco: el método equals de Entero devuelve verdadero si los dos valores numéricos son iguales, mientras que el método de igual de Objeto devolverá verdadero solo si es el mismo objeto, 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 todavía es un poco confuso, recomiendo leer los siguientes tutoriales:


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



Aquí hay un fragmento simple que puede usar en lugar de una gran biblioteca de guayaba:

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

Vea todo el ejemplo de trabajo


Basándose en el ejemplo de Vlad para trabajar con mapas de diferentes tamaños

public static <K, V> Map<K, V> mapDiff(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(left.size() <= right.size() ? left.entrySet() : right.entrySet()); return difference; }