I have map with key as String and value as List. List can have 10 unique values. I need to convert this map with key as Integer and value as List. Example as below :
It's a bit scary (I generally try to break it down to make it more readable) but you could do it this way:
Map<Integer, List<String>> transposeMap = new HashMap<>();
map.forEach((key, list) -> list.stream().forEach(
elm -> transposeMap.put(elm,
transposeMap.get(elm) == null ? Arrays.asList(key) : (Stream.concat(transposeMap.get(elm).stream(),
Arrays.asList(key).stream()).collect(Collectors.toList())))));
Assuming Map<String, List<Integer>> map
is your original Map that you want to transpose. transposeMap
will have transposed map that you need.
You can Achieve in this way
Let suppose I have Person class with Gender and Age . I want to get it in this form
Map<SEX,List<Person>>
I would write simply
Map<SEX,List<Person>> map = personList.stream()
.collect(Collectors.groupingBy(Person::getGender));
it will get me something like below (one key against multiple values )
key:MALE
age31sexMALE
age28sexMALE
key:FEMALE
age40sexFEMALE
age44sexFEMALE
An idea could be to generate all value-key pairs from the original map and then group the keys by these values:
import java.util.AbstractMap.SimpleEntry;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.mapping;
import static java.util.stream.Collectors.toList;
...
Map<Integer, List<String>> transposeMap =
map.entrySet()
.stream()
.flatMap(e -> e.getValue().stream().map(i -> new SimpleEntry<>(i, e.getKey())))
.collect(groupingBy(Map.Entry::getKey, mapping(Map.Entry::getValue, toList())));
Alexis’ answer contains the general solution for this kind of task, using flatMap
and a temporary holder for the combination of key and flattened value. The only alternative avoiding the creation of the temporary holder objects, is to re-implement the logic of the groupingBy
collector and inserting the loop over the value list logic into the accumulator function:
Map<Integer, List<String>> mapT = map.entrySet().stream().collect(
HashMap::new,
(m,e) -> e.getValue().forEach(
i -> m.computeIfAbsent(i,x -> new ArrayList<>()).add(e.getKey())),
(m1,m2) -> m2.forEach((k,v) -> m1.merge(k, v, (l1,l2)->{l1.addAll(l2); return l1;})));