2012-05-14 24 views
14

En java, quiero comparar dos mapas, como a continuación, ¿tenemos API existente para hacer esto?Java compare dos mapa

Gracias

Map<String, String> beforeMap ; 
beforeMap.put("a", "1"); 
beforeMap.put("b", "2"); 
beforeMap.put("c", "3"); 

Map<String, String> afterMap ; 
afterMap.put("a", "1"); 
afterMap.put("c", "333"); 

//--- it should give me: 
b is missing, c value changed from '3' to '333' 
+0

No creo que haya una API predeterminada para esto. Necesitas codificar la lógica. – kosa

+1

posible duplicado de [cómo comparar dos mapas hash?] (Http://stackoverflow.com/questions/4591988/how-to-compare-two-hash-maps) –

Respuesta

26

que haría uso de la funcionalidad removeAll() del conjunto a hacer diferencias conjunto de claves para encontrar las adiciones y supresiones. Los cambios reales se pueden detectar haciendo una diferencia de conjunto usando la entrada establecida como HashMap. Entry implementa equals() usando tanto la clave como el valor.

Set<String> removedKeys = new HashSet<String>(beforeMap.keySet()); 
removedKeys.removeAll(afterMap.keySet()); 

Set<String> addedKeys = new HashSet<String>(afterMap.keySet()); 
addedKeys.removeAll(beforeMap.keySet()); 

Set<Entry<String, String>> changedEntries = new HashSet<Entry<String, String>>(
     afterMap.entrySet()); 
changedEntries.removeAll(beforeMap.entrySet()); 

System.out.println("added " + addedKeys); 
System.out.println("removed " + removedKeys); 
System.out.println("changed " + changedEntries); 

salida

added [] 
removed [b] 
changed [c=333] 
+1

Downvoter Respuesta: "¡Porque la ciencia!" Bromeando. Gran respuesta. +1 –

1

No es ningún componente del cuadro para ayudar con eso. Probablemente tendrás que codificarlo desafortunadamente. La buena noticia es que la lógica es bastante fácil.

1

Dependiendo de sus necesidades particulares, también podría considerar el uso de otras aplicaciones diseñadas para hacer este trabajo, como diff. Puede escribir los dos mapas en dos archivos diferentes y distinguir los archivos.

10

La clase Guava Maps tiene algunos métodos para calcular las diferencias entre un par de mapas. Sin embargo, estos métodos le dan una estructura de datos que representa las diferencias, no una cadena bastante impresa.

1

Se puede usar un objeto personalizado que contiene la clave y el valor (en realidad Mapa hace esto internamente, oculto al usuario, por lo que no puede usar eso)

poner estas tuplas en una Set

Para comparar dos conjuntos, conviértalos en matrices, ordene las matrices y recorra ambas matrices de principio a fin en paralelo, reduciendo la primera matriz si su clave es más pequeña que la clave en la segunda matriz, y viceversa.

class Tuple implements Comparable<Tuple> 
{ 
    public String key; 
    public String value; 

    public Tuple(String key, String value) 
    { 
     this.key = key; 
     this.value = value; 
    } 

    @Override 
    public int compareTo(Tuple o) 
    { 
     return key.compareTo(o.key); 
    } 
} 

public static void main(String[] args) 
{ 
    // TreeSet is already sorted. If you use HashSet, use Arrays.sort() 
    Set<Tuple> beforeSet = new TreeSet<>(); 
    beforeSet.add(new Tuple("a", "1")); 
    beforeSet.add(new Tuple("b", "2")); 
    beforeSet.add(new Tuple("c", "4")); 

    Set<Tuple> afterSet = new TreeSet<>(); 
    afterSet.add(new Tuple("a", "1")); 
    afterSet.add(new Tuple("c", "333")); 
    afterSet.add(new Tuple("aa", "4")); 

    Tuple[] beforeArray = beforeSet.toArray(new Tuple[beforeSet.size()]); 
    Tuple[] afterArray = afterSet.toArray(new Tuple[afterSet.size()]); 

    int beforePtr = 0; 
    int afterPtr = 0; 
    while (beforePtr < beforeArray.length || afterPtr < afterArray.length) 
    { 
     int difference = afterPtr >= afterArray.length? -1 : beforePtr >= beforeArray.length? 1 : beforeArray[beforePtr].compareTo(afterArray[afterPtr]); 
     if (difference == 0) 
     { 
      if (!beforeArray[beforePtr].value.equals(afterArray[afterPtr].value)) 
      { 
       System.out.println(beforeArray[beforePtr].key + " value changed from '" + beforeArray[beforePtr].value + "' to '" + afterArray[afterPtr].value + "'"); 
      } 
      beforePtr++; 
      afterPtr++; 
     } 
     else if (difference < 0) 
     { 
      System.out.println(beforeArray[beforePtr].key + " is missing"); 
      beforePtr++; 
     } 
     else 
     { 
      System.out.println(afterArray[afterPtr].key + " is added"); 
      afterPtr++; 
     } 
    } 
} 
1
String output = new String(); 
for (String key:beforeMap.getKeys()){ 
    String beforeValue = beforeMap.getValue(key); 
    String afterValue = afterMap.getValue(key); 
    //nullsafe 
    if(beforeValue.equals(afterValue){} 
    else if (afterValue == null){ 
     output = output + key + " is missing, "; 
     continue; 
    }else { 
     output = output + key + " has changed from " + beforeValue + " to " + afterValue + " , "; 
    } 
    afterMap.remove(key); 

} 

for (String key:afterMap.getKeys()){ 
    output = output + key + " was added with value " + afterMap.getValue(key) + ", "; 
} 

if(output == null){ 
    output = "Same map"; 
} 
output = output.substring(0,output.length-2); 
System.out.println(output); 
0

@ user595234 para comparar los dos mapas se pueden agregar las claves de un mapa a la lista y con esos 2 listas se pueden utilizar los métodos retainAll() y removeAll() y agréguelos a otra lista de teclas comunes y a una lista de teclas diferentes. Usando las teclas de la lista común y la lista diferente puede iterar a través del mapa, usando iguales puede comparar los mapas.

public class Demo 
    { 
      public static void main(String[] args) 
      { 
       Map<String, String> beforeMap = new HashMap<String, String>(); 
       beforeMap.put("a", "1"); 
       beforeMap.put("b", "2"); 
       beforeMap.put("c", "3"); 

       Map<String, String> afterMap = new HashMap<String, String>(); 
       afterMap.put("a", "1"); 
       afterMap.put("c", "333"); 

       System.out.println("Before "+beforeMap); 
       System.out.println("After "+afterMap); 

       List<String> beforeList = getAllKeys(beforeMap); 

       List<String> afterList = getAllKeys(afterMap); 

       List<String> commonList1 = beforeList; 
       List<String> commonList2 = afterList; 
       List<String> diffList1 = getAllKeys(beforeMap); 
       List<String> diffList2 = getAllKeys(afterMap); 

       commonList1.retainAll(afterList); 
       commonList2.retainAll(beforeList); 

       diffList1.removeAll(commonList1); 
       diffList2.removeAll(commonList2); 

       System.out.println("Common List of before map "+commonList1); 
       System.out.println("Common List of after map "+commonList2); 
       System.out.println("Diff List of before map "+diffList1); 
       System.out.println("Diff List of after map "+diffList2); 

       if(commonList1!=null & commonList2!=null) // athough both the size are same 
       { 
        for (int i = 0; i < commonList1.size(); i++) 
        { 
         if ((beforeMap.get(commonList1.get(i))).equals(afterMap.get(commonList1.get(i)))) 
         { 
          System.out.println("Equal: Before- "+ beforeMap.get(commonList1.get(i))+" After- "+afterMap.get(commonList1.get(i))); 
         } 
         else 
         { 
          System.out.println("Unequal: Before- "+ beforeMap.get(commonList1.get(i))+" After- "+afterMap.get(commonList1.get(i))); 
         } 
        } 
       } 
       if (CollectionUtils.isNotEmpty(diffList1)) 
       { 
        for (int i = 0; i < diffList1.size(); i++) 
        { 
         System.out.println("Values present only in before map: "+beforeMap.get(diffList1.get(i))); 
        } 
       } 
       if (CollectionUtils.isNotEmpty(diffList2)) 
       { 
        for (int i = 0; i < diffList2.size(); i++) 
        { 
         System.out.println("Values present only in after map: "+afterMap.get(diffList2.get(i))); 
        } 
       } 
      } 

      /** getAllKeys API adds the keys of the map to a list */ 
      private static List<String> getAllKeys(Map<String, String> map1) 
      { 
       List<String> key = new ArrayList<String>(); 
       if (map1 != null) 
       { 
        Iterator<String> mapIterator = map1.keySet().iterator(); 
        while (mapIterator.hasNext()) 
        { 
         key.add(mapIterator.next()); 
        } 
       } 
       return key; 
      } 
    } 

El código de abajo le dará esta salida:

Antes: {b=2, c=3, a=1}
Después: {c=333, a=1}
desigual: para antes después del horario 3 333
Igualdad: 1 para antes después del horario 1
Los valores están presentes solo en el mapa anterior: 2

+0

también puede usar la MultiValueMap de org.apache.commons.collections.map –