How could I do the following with Java Streams?
Let's say I have the following classes:
class Foo { Bar b; } class Bar { String id; String date; }
I have a List<Foo>
and I want to convert it to a Map <Foo.b.id, Map<Foo.b.date, Foo>
. I.e: group first by the Foo.b.id
and then by Foo.b.date
.
I'm struggling with the following 2-step approach, but the second one doesn't even compile:
Map<String, List<Foo>> groupById = myList .stream() .collect( Collectors.groupingBy( foo -> foo.getBar().getId() ) ); Map<String, Map<String, Foo>> output = groupById.entrySet() .stream() .map( entry -> entry.getKey(), entry -> entry.getValue() .stream() .collect( Collectors.groupingBy( bar -> bar.getDate() ) ) );
Thanks in advance.
With Java 8, you can convert a List to Map in one line using the stream() and Collectors. toMap() utility methods. The Collectors. toMap() method collects a stream as a Map and uses its arguments to decide what key/value to use.
Method 1: Using Collectors.toMap() Function The Collectors. toMap() method takes two parameters as the input: KeyMapper: This function is used for extracting keys of the Map from stream value. ValueMapper: This function used for extracting the values of the map for the given key.
Converting only the Value of the Map<Key, Value> into Stream: This can be done with the help of Map. values() method which returns a Set view of the values contained in this map. In Java 8, this returned set can be easily converted into a Stream of key-value pairs using Set. stream() method.
You can group your data in one go assuming there are only distinct Foo
:
Map<String, Map<String, Foo>> map = list.stream() .collect(Collectors.groupingBy(f -> f.b.id, Collectors.toMap(f -> f.b.date, Function.identity())));
Saving some characters by using static imports:
Map<String, Map<String, Foo>> map = list.stream() .collect(groupingBy(f -> f.b.id, toMap(f -> f.b.date, identity())));
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