Java 8 Stream:
Map<String, List<String>> mapGlobal = new HashMap<String, List<String>>();
Map<String, List<String>> mapAdded = new HashMap<String, List<String>>();
私はこの実装を使用しようとします:
mapGlobal = Stream.of(mapGlobal, mapAdded)
.flatMap(m -> m.entrySet().stream())
.collect(Collectors.groupingBy(Map.Entry::getKey,
Collectors.mapping(Map.Entry::getValue,
Collectors.toList())
));
ただし、この実装では次のような結果のみが作成されます。
Map<String, List<Object>>
1つのキーがmapGlobal
に含まれていない場合、対応する文字列のリストとともに新しいキーとして追加されます。キーがmapGlobal
とmapAdded
で重複している場合、両方の値のリストが次のようにマージされます:A = {1, 3, 5, 7}
およびB = {1, 2, 4, 6}
、次にA ∪ B = {1, 2, 3, 4, 5, 6, 7}
。
これを行うには、mapAdded
のすべてのエントリを繰り返し処理し、mapGlobal
にマージします。
次のコードは、 forEach(action)
を呼び出してmapAdded
のエントリを反復処理し、アクションが各エントリのキーと値を消費します。エントリごとに、mapGlobal
で merge(key, value, remappingFunction)
を呼び出します。これにより、キーk
の下にエントリが作成され、キーが存在しない場合は値v
が作成されます。指定された再マッピング関数が既に存在する場合は、それらを呼び出します。この関数は、マージする2つのリストを取得します。この場合、最初にTreeSet
に追加され、一意の要素と並べ替えられた要素の両方を確実にし、リストに変換し直します。
_mapAdded.forEach((k, v) -> mapGlobal.merge(k, v, (v1, v2) -> {
Set<String> set = new TreeSet<>(v1);
set.addAll(v2);
return new ArrayList<>(set);
}));
_
これを並列で実行する可能性がある場合は、entrySet()
を取得してparallelStream()
を呼び出すことにより、Streamパイプラインを作成できます。ただし、その場合は、mapGlobal
のように、ConcurrentHashMap
の同時実行をサポートするマップを使用する必要があります。
_ConcurrentMap<String, List<String>> mapGlobal = new ConcurrentHashMap<>();
// ...
mapAdded.entrySet().parallelStream().forEach(e -> mapGlobal.merge(e.getKey(), e.getValue(), (v1, v2) -> {
Set<String> set = new TreeSet<>(v1);
set.addAll(v2);
return new ArrayList<>(set);
}));
_
Foreach over Mapを使用すると、指定されたarraylistをマージできます。
public Map<String, ArrayList<String>> merge(Map<String, ArrayList<String>> map1, Map<String, ArrayList<String>> map2) {
Map<String, ArrayList<String>> map = new HashMap<>();
map.putAll(map1);
map2.forEach((key , value) -> {
//Get the value for key in map.
ArrayList<String> list = map.get(key);
if (list == null) {
map.put(key,value);
}
else {
//Merge two list together
ArrayList<String> mergedValue = new ArrayList<>(value);
mergedValue.addAll(list);
map.put(key , mergedValue);
}
});
return map;
}
元の実装はMap<String, List<Object>>
のような結果を作成しませんが、Map<String, List<List<String>>>
を作成します。 Map<String, List<String>>
を生成するには、追加のStreamパイプラインが必要です。
StreamEx の使用
Map<String, List<String>> mergedMap =
EntryStream.of(mapGlobal)
.append(EntryStream.of(mapAdded))
.toMap((v1, v2) -> {
List<String> combined = new ArrayList<>();
combined.addAll(v1);
combined.addAll(v2);
return combined;
});
マージするマップがさらにある場合は、ストリームに追加するだけです
.append(EntryStream.of(mapAdded2))
.append(EntryStream.of(mapAdded3))