问题
I have a List like this:
List<Map<String, Long>>
Is there a way, using lambda, to convert this list to:
Map<String, List<Long>>
Example:
Map<String, Long> m1 = new HashMap<>();
m1.put("A", 1);
m1.put("B", 100);
Map<String, Long> m2 = new HashMap<>();
m2.put("A", 10);
m2.put("B", 20);
m2.put("C", 100);
List<Map<String, Long>> beforeFormatting = new ArrayList<>();
beforeFormatting.add(m1);
beforeFormatting.add(m2);
After formatting:
Map<String, List<Long>> afterFormatting;
which would look like:
A -> [1, 10]
B -> [100, 20]
C -> [100]
回答1:
You need to flatMap
the entry set of each Map to create a Stream<Map.Entry<String, Long>>
. Then, this Stream can be collected with the groupingBy(classifier, downstream) collector: the classifier returns the key of the entry and the downstream collector maps the entry to its value and collects that into a List
.
Map<String, List<Long>> map =
list.stream()
.flatMap(m -> m.entrySet().stream())
.collect(groupingBy(Map.Entry::getKey, mapping(Map.Entry::getValue, toList())));
This code needs the following static imports:
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.mapping;
import static java.util.stream.Collectors.toList;
With your full example:
public static void main(String[] args) {
Map<String, Long> m1 = new HashMap<>();
m1.put("A", 1l);
m1.put("B", 100l);
Map<String, Long> m2 = new HashMap<>();
m2.put("A", 10l);
m2.put("B", 20l);
m2.put("C", 100l);
List<Map<String, Long>> beforeFormatting = new ArrayList<>();
beforeFormatting.add(m1);
beforeFormatting.add(m2);
Map<String, List<Long>> afterFormatting =
beforeFormatting.stream()
.flatMap(m -> m.entrySet().stream())
.collect(groupingBy(Map.Entry::getKey, mapping(Map.Entry::getValue, toList())));
System.out.println(afterFormatting); // prints {A=[1, 10], B=[100, 20], C=[100]}
}
来源:https://stackoverflow.com/questions/34174527/grouping-by-list-of-map-in-java-8