Reputation: 11806
How can I build a map based on two others maps using Java 8 streams? Namely, I have the following map structures:
map1 = Map<MyModel, List<String>>();
map2 = Map<String, String>();
where List<String>
values of map1
are the identical with String
keys in map2
. In other words based on map1 values
one can use it as keys
in map2
and get values
from there.
So, my question is how to merge those two maps with usage of streams and lambdas techniques and build a new map which will include MyModel as keys
and List<Strings> as values
with no duplicates?
This what I have so far:
map1 = Map<MyModel, List<String>>();
map2 = Map<String, String>();
Map<MyModel, List<String>> map3 = Stream.of(map1, map2)
.flatMap(map -> map.entrySet().stream())
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(v1, v2) -> v1
)
);
Any help would be appreciated.
Upvotes: 2
Views: 4852
Reputation: 28133
Lets start with transforming a List<String> list
by looking up values form map2
and discarding duplicates:
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
.....
list.stream()
.filter(map2::containsKey) // make sure map2 has this key
.map(map2::get) // get the value
.distinct() // discard duplicates
.collect(toList()); // make new list
Now you just have to use the above as the value mapper (with static imports of Collectors
methods) to solve your problem:
map1.entrySet().stream().collect(toMap(
Map.Entry::getKey,
e -> e.getValue().stream()
.filter(map2::containsKey)
.map(map2::get)
.distinct()
.collect(toList())
));
Upvotes: 3
Reputation: 1005
Below is something I thought of quickly. There may be a more efficient way to implement your requirements but it will at least give you a start.
Code
public static void main(String[] args) {
//Map 1
Map<Integer, List<String>> map1 = new HashMap<>();
map1.put(1, Arrays.asList("A", "B"));
map1.put(2, Arrays.asList("C", "D"));
//Map 2
Map<String, String> map2 = new HashMap<>();
map2.put("A", "Apple");
map2.put("B", "Banana");
map2.put("C", "Cherries");
map2.put("D", "Dewberries");
Map<Integer, List<String>> collect = map1.entrySet()
.stream()
.map(entry -> {
return new AbstractMap.SimpleImmutableEntry<>(
entry.getKey(),
entry.getValue()
.stream()
.map(map2::get)
.filter(Objects::nonNull)
.collect(Collectors.toList())
);
})
.collect(Collectors.toMap(AbstractMap.SimpleImmutableEntry::getKey, AbstractMap.SimpleImmutableEntry::getValue));
System.out.println(collect);
}
Output
{1=[Apple, Banana], 2=[Cherries, Dewberries]}
Upvotes: 1