4

I have 2 Maps

Map<A, B> mapA
Map<B, List<C>> mapB

I want to join these maps on the values in mapA & keys in mapB the result should be

Map<A,List<C>> mapC

I am willing to know how can I do it using streams in Java8.

A,B,C for simplicty, all of these are strings in my case.

  • 5
    Have you tried anything? Read the documentation? What concrete problem did you face? Regardless of the syntax, what would be your strategy to achieve that? – JB Nizet Oct 25 '18 at 20:39
  • 2
    `map.entrySet().stream().collect(Collectors.toMap(Entry::getKey, e -> mapB.get(e.getValue())))` – shmosel Oct 25 '18 at 20:41
  • @BillK I think your solution will neither compile, nor it is what the OP asked – Kartik Oct 25 '18 at 23:33
  • @BillK dont think so your solution will work. I am trying to create a 3rd map from values of A matching keys of B – ayush sanghvi Oct 26 '18 at 00:25
  • @BillK I completely agree with what you said regarding streams. But your code still won't compile. (1) `addAll` is in `Collection` interface. `Map` has `putAll` instead. (2) You are trying to add all `Map` to `Map>`, which won't work! – Kartik Oct 26 '18 at 00:26
  • @shmosel could you please post your answers as answers and not as comments? Because (1) visitors might miss out on a better solution like yours and (2) I come up with the same solution but am ashamed to post it as an answer as you have already posted it in the comments. Thanks. :) – Kartik Oct 26 '18 at 00:31
  • @Kartik I usually do it as a lazy response to a lazy question, but by all means, post it as an answer if you like. – shmosel Oct 26 '18 at 00:43
  • @Kartic you are right.. I'm deleting my comments. I Absolutely missed a point that should have been obvious. – Bill K Oct 26 '18 at 00:52

2 Answers2

4

You can iterate over the map and easily construct the new map.

Map<A,List<C>> mapC = new HashMap<>();

mapA.forEach((key,value)->mapC.put(key, mapB.get(value)));

You can use this link, which compares the efficiency of different ways to iterate over the key-value pairs, to select which method you want to use.

uneq95
  • 2,158
  • 2
  • 17
  • 28
3

You could do it like this:

mapC = mapA.entrySet()
        .stream()
        .collect(Collectors.toMap(Map.Entry::getKey, e -> mapB.get(e.getValue())));
Kartik
  • 7,677
  • 4
  • 28
  • 50
  • Why create an entry set, then make a stream out of it and then finally collect them, if you cam just use Map.forEach which directly gives you the key value pair. It makes it easier and simpler to understand. – uneq95 Oct 26 '18 at 02:54
  • @uneq95 Stream operations don't work in the sequence as you might think they do. Performance, memory consumption and readability are similar to those of your solution, if not better. – Kartik Oct 26 '18 at 02:58
  • Yes, I know that it doesn't work in sequence. Neither do we require the sequence to be maintained here, as we just want to insert in a hashmap, which too doesn't maintain the sequence. I was arguing on the creation of entry set in the first place. – uneq95 Oct 26 '18 at 03:07
  • @uneq95 I was talking about the sequence of stream operations, like conversion to stream, running filter, map, etc. and then collecting. I was not talking about the ordering of elements in the result. Try asking a new question to see which solution is better and you'll get the answer that they are similar. – Kartik Oct 26 '18 at 03:13
  • 3
    @uneq95 There's no "creation" of an entry set. It's just a thin view to the underlying map. – shmosel Oct 26 '18 at 07:35
  • @shmosel given that a lot of maps are implemented with a data structure which is basically a set of entries, you can also see it the other way round, the `Map` is an alternative API to the entry set. Especially, as the only method, subclasses of `AbstractMap` need to implement, is `entrySet()`. – Holger Oct 26 '18 at 11:39