17

Java で、以下のように 2 つのマップを比較したいのですが、これを行うための既存の API はありますか?

ありがとう

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'
4

7 に答える 7

31

Set の removeAll() 機能を使用して、キーの違いを設定し、追加と削除を見つけます。実際の変更は、HashMap.Entry がキーと値の両方を使用して equals() を実装するため、エントリ セットを使用してセット差分を実行することで検出できます。

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

出力

added []
removed [b]
changed [c=333]
于 2012-05-14T16:16:37.053 に答える
9

GuavaMapsクラスには、マップのペア間の差を計算するためのメソッドがいくつかあります。ただし、これらのメソッドは、きれいに印刷された文字列ではなく、違いを表すデータ構造を提供します。

于 2012-05-14T16:10:02.793 に答える
1

それを支援するすぐに使えるコンポーネントはありません。残念ながら、おそらくコーディングする必要があります。幸いなことに、ロジックは非常に簡単です。

于 2012-05-14T16:03:44.623 に答える
1

特定のニーズに応じて、diff など、この作業を行うように設計された他のアプリケーションの使用を検討することもできます。2 つのマップを 2 つの異なるファイルに書き込んで、ファイルを比較することができます。

于 2012-05-14T16:08:46.837 に答える
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);
于 2012-05-14T16:18:40.127 に答える
1

キーと値を含むカスタム オブジェクトを使用できます (実際には Map は内部でこれを行い、ユーザーからは隠されているため、使用できません)。

これらのタプルをSet

2 つのセットを比較するには、両方を配列に変換し、配列を並べ替えて、両方の配列を最初から最後まで並行してウォークし、最初の配列のキーが 2 番目の配列のキーより小さい場合はステップ ダウンし、その逆も同様です。

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++;
        }
    }
}
于 2012-05-14T16:11:30.697 に答える
0

@ user595234 2 つのマップを比較するには、マップのキーをリストに追加できます。これらの 2 つのリストでは、retainAll() および removeAll() メソッドを使用して、それらを別の共通キー リストおよび異なるキー リストに追加できます。共通リストと異なるリストのキーを使用してマップを反復処理し、equals を使用してマップを比較できます。

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

以下のコードは、この出力を提供します。

前:{b=2, c=3, a=1}
後:{c=333, a=1}
不等: 前- 3 後- 333
等しい: 前- 1 後- 1
前マップのみに存在する値: 2

于 2012-12-10T11:34:10.550 に答える