Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inverse Map where getValue returns a List

I would like to transform a Map<String, List<Object>> so it becomes Map<String, String>. If it were just Map<String, Object> it is easy in Java8;

stream().collect(k -> k.getValue().getMyKey(), Entry::getKey);

But this will not work because getValue returns a List Map<List<Object>, String> in my example. Assume Object contains a getter to be used for the key and that Object does not contain the key in the first map.

Any thoughts?

like image 292
cbm64 Avatar asked Nov 27 '18 11:11

cbm64


2 Answers

Stream over the list of objects and extract the key you need then map --> flatten --> toMap

source.entrySet()
      .stream()
      .flatMap(e -> e.getValue()
                     .stream()
                     .map(x -> new SimpleEntry<>(x.getMyKey(), e.getKey())))
      .collect(toMap(SimpleEntry::getKey, SimpleEntry::getValue));

use a merge function if there is expected to be duplicate getMyKey() values:

source.entrySet()
      .stream()
      .flatMap(e -> e.getValue()
                     .stream()
                     .map(x -> new SimpleEntry<>(x.getMyKey(), e.getKey())))
      .collect(toMap(SimpleEntry::getKey, SimpleEntry::getValue, (l, r) -> l));

Note: the above uses the source map keys as the values of the resulting map as that's what you seem to be illustrating in your post, if however you want the key of the source map to remain as the key of the resulting map then change new SimpleEntry<>(x.getMyKey(), e.getKey()) to new SimpleEntry<>(e.getKey(),x.getMyKey()).

like image 109
Ousmane D. Avatar answered Nov 13 '22 23:11

Ousmane D.


If preference could be to choose any amongst the multiple values mapped as a key, you can simply use:

Map<String, List<YourObject>> existing = new HashMap<>();
Map<String, String> output = new HashMap<>();
existing.forEach((k, v) -> v.forEach(v1 -> output.put(v1.getMyKey(), k)));

Essentially this would put the 'first' such myKey along with its corresponding value which was the key of the existing map.

like image 36
Naman Avatar answered Nov 13 '22 23:11

Naman