bofanda
bofanda

Reputation: 11806

Create Map based on two other maps in Java

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

Answers (2)

Misha
Misha

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

Garreth Golding
Garreth Golding

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

Related Questions