Reputation: 127
Suppose there are 2 maps such that values of 1st map are keys of 2nd map, as show below
Map1 { k1:[v1,v2,v3], k2:[v4,v5], k3:[v6,v7,v8] }
Map2 { v1:[a1,a2], v2:[a3,a4,a5], v3:[a6], v4:[a7,a8], v5:[a9,a10,a11], v6[a1,a3], v7[a1,a9], v8[a2,a4,a5] }
I want to make a map say Map3 from the above 2 maps such that
Map3 {
k1:[a1,a2,a3,a4,a5,a6],
k2:[a7,a8,a9,a10,a11],
k3:[a1,a2,a3,a4,a5,a9]
}
Are there any inbuilt methods in Java8 Collections API which I can use to derive Map3 in an efficient way, rather than iterating over both the maps to get Map3 in the old Java5 way.
Upvotes: 0
Views: 397
Reputation: 17299
Alternative solution is:
Map<String, List<String>> result =
map1.entrySet().stream()
.collect(HashMap::new, (m, e) -> m.merge(e.getKey(),
e.getValue().stream().flatMap(k -> map2.get(k).stream()).collect(toList()),
(l1, l2) -> { l1.addAll(l2);return l1; }),
Map::putAll);
Upvotes: 2
Reputation: 40062
I would approach it like this.
In your example, assuming the types are all String, call it it like this.
Map<String,Set<String>> map3 = reMap(map1,map2);
public static <K, V, R> Map<K, Set<R>> reMap(
Map<K, List<V>> map1, Map<V, List<R>> map2) {
Map<K, Set<R>> map3 = new HashMap<>();
for (Map.Entry<K, List<V>> e : map1.entrySet()) {
for (V map2key : e.getValue()) {
map3.compute(e.getKey(),
(k, v) -> v == null
? new HashSet<>()
: v)
.addAll(map2.get(map2key));
}
}
return map3;
}
Upvotes: 0
Reputation: 51093
Here's a solution using streams:
return map1.entrySet().stream().collect(
Collectors.toMap(
Map.Entry::getKey,
e -> e.getValue().stream()
.map(map2::get)
.flatMap(List::stream)
.distinct()
.collect(Collectors.toList())));
Output:
{k1=[a1, a2, a3, a4, a5, a6],
k2=[a7, a8, a9, a10, a11],
k3=[a1, a3, a9, a2, a4, a5]}
You can add .sorted()
after .distinct()
if you want the k3
list to be in order.
Upvotes: 1