0

I hope all is good for you.

I have two maps Map<Type1, Type2> and a Map<Type3, Type1>. I want to merge them and have at the end a Map<Type3, Type2>.

How can I do that? I make this code but the result is Map<Type1, Type2>

Map<Type3, Type2> result =
    Stream.of(map1.keySet(), map2.values())
        .flatMap(Collection::stream)
        .toList()
        .stream()
        .filter(
            id ->
                map1.containsKey(id)
                    && map2.containsValue(id))
        .collect(
            Collectors.toMap(
                map2::get,
                map1::get,
                (v1, v2) -> StringUtils.isNotEmpty(v1) ? v1 : v2));

Thanks for your help.

2
  • map2.forEach((t3, t1) -> result.put(t3, map1.get(t1))); Commented Sep 6, 2023 at 23:43
  • One way I can think of is iterating over the entries of the second map (Map<Type3, Type1>) and using the values (Type1) to look up the corresponding values (Type2) in the first map (Map<Type1, Type2>) Commented Sep 6, 2023 at 23:44

2 Answers 2

4

containsValue is very expensive; it's a full loop. So definitely do not do that.

Collecting into a map requires that you design a function that turns a stream element into a key, and a second function that turns a stream element into a value. That's not very difficult here. T3 remains, it's just that the value of your T3->T1 map needs to be adjusted.

import java.util.AbstractMap.SimpleImmutableEntry;

Map<Type3, Type1> map1 = ...;
Map<Type1, Type2> map2 = ...;

Map<Type3, Type2> result = map1.entrySet().stream()
  .map(entry -> new SimpleImmutableEntry<>(entry.getKey(), map2.get(entry.getValue())))
  .filter(entry -> entry.getValue() != null)
  .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

This:

  • goes through every K/V pair in your T3->T1 map.
  • Turns each such pair into a T3->T2 pair instead, by looking up the T1 value in the T1->T2 map.
  • Assuming you want any k/v pairs in the T3->T1 map where the value is not in the T1->T2 map to just be removed, we then filter it out, (ab)using null as a go-between. We could have filtered with .filter(entry -> map2.containsKey(entry.getValue()) too, but this way we save 1 lookup.
  • These map entries are already exactly what we want, so we just reconstitute that back into a map.
Sign up to request clarification or add additional context in comments.

Comments

0

One way I can think of is iterating over the entries of the second map (Map<Type3, Type1>) and using the values (Type1) to look up the corresponding values (Type2) in the first map (Map<Type1, Type2>)

Map<Type3, Type2> result = new HashMap<>();
for (Map.Entry<Type3, Type1> entry : map2.entrySet()) {
    Type3 key = entry.getKey();
    Type1 value = entry.getValue();
    Type2 otherValue = map1.get(value);
    result.put(key, otherValue);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.