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]
In Java 8, you retrieve the stream from the list and use a Collector to group them in one line of code. It's as simple as passing the grouping condition to the collector and it is complete. By simply modifying the grouping condition, you can create multiple groups.
The groupingBy() method of Collectors class in Java are used for grouping objects by some property and storing results in a Map instance. In order to use it, we always need to specify a property by which the grouping would be performed. This method provides similar functionality to SQL's GROUP BY clause.
groupingBy. Returns a Collector implementing a cascaded "group by" operation on input elements of type T , grouping elements according to a classification function, and then performing a reduction operation on the values associated with a given key using the specified downstream Collector .
In Java 8 Streams, the flatMap() method applies operation as a mapper function and provides a stream of element values. It means that in each iteration of each element the map() method creates a separate new stream. By using the flattening mechanism, it merges all streams into a single resultant stream.
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]}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With