1年近く前に、リストの比較を書いた。
リストの比較、ListDiff - Oboe吹きプログラマの黙示録
それなら2つのマップの比較も普遍的なものが書けるであろう。
import java.util.Map; import java.util.function.BiFunction; import java.util.function.Consumer; /** * MapDiff */ public final class MapDiff<K, V>{ private BiFunction<V, V, Boolean> matchFunction; private Consumer<K> leftonly; private Consumer<K> rightonly; private Consumer<K> diffConsumer; private Consumer<K> matchConsumer; private MapDiff(BiFunction<V, V, Boolean> matchFunction){ this.matchFunction = matchFunction; } /** * MapDiffインスタンス生成. * @param matchFunction 比較する2つのMapのValue要素を等しいと判定する BiFunction で Boolean(true=等しい) を返す。 * @return ListDiff<T>{ */ public static <K, V> MapDiff<K, V> of(BiFunction<V, V, Boolean> matchFunction){ return new MapDiff<>(matchFunction); } /** * 左側(1番目指定)Mapだけに所属するkeyの Consumerを登録. * @param leftonly Consumer<K> */ public void leftOnly(Consumer<K> leftonly){ this.leftonly = leftonly; } /** * 右側(2番目指定)Mapだけに所属するkeyの Consumerを登録. * @param rightonly Consumer<K> */ public void rightOnly(Consumer<K> rightonly){ this.rightonly = rightonly; } /** * MapのValue値が異なるkeyの Consumerを登録. * @param biConsumer Consumer<K> */ public void unmatch(Consumer<K> diffConsumer){ this.diffConsumer = diffConsumer; } /** * MapのKeyとValue値が同じkeyの Consumerを登録. * @param biConsumer Consumer<K> */ public void match(Consumer<K> matchConsumer){ this.matchConsumer = matchConsumer; } /** * Mapの比較. * @param leftMap * @param rightMap */ public void diff(Map<K, V> leftMap, Map<K, V> rightMap){ leftMap.entrySet().stream().forEach(e->{ K k = e.getKey(); if (rightMap.containsKey(k)){ if (matchFunction.apply(e.getValue(), rightMap.get(k))){ if (matchConsumer != null) matchConsumer.accept(k); }else{ if (diffConsumer != null) diffConsumer.accept(k); } }else{ if (leftonly != null) leftonly.accept(k); } }); if (rightonly != null){ rightMap.keySet().forEach(key->{ if (!leftMap.containsKey(key)) rightonly.accept(key); }); } } /** * Mapの比較. * @param map1 マップ1 * @param map2 マップ2 * @param match 値が一致するかを返す BiFunction<V, V, Boolean> * @param leftOnly マップ1に対してマップ2で削除されたキーのConsumer<K> * @param rightOnly マップ1に対してマップ2で追加されたキーのConsumer<K> * @param mc マップ1に対してマップ2で変更されたキーのConsumer<K> */ public static <K, V> void diffMap(Map<K, V> map1, Map<K, V> map2, BiFunction<V, V, Boolean> match , Consumer<K> leftOnly, Consumer<K> rightOnly, Consumer<K> mc){ map1.entrySet().stream().forEach(e->{ K k = e.getKey(); if (map2.containsKey(k)){ if (!match.apply(e.getValue(), map2.get(k))) mc.accept(k);; }else{ leftOnly.accept(k); } }); map2.keySet().forEach(key->{ if (!map1.containsKey(key)) rightOnly.accept(key); }); } }
だいたいこんなかんじで使う
MapDiff<Integer, String> m = MapDiff.of((v1, v2)->v1.equals(v2)); m.leftOnly(k->leftMap.put(k, map1.get(k))); m.rightOnly(k->rightMap.put(k, map2.get(k))); m.unmatch(k->dMap.put(k, map1.get(k) + "→" + map2.get(k))); m.diff(map1, map2);