Java Reference
In-Depth Information
The code collects the names for a group in a comma-separated
String
. Can you think of a way to collect the
names in a
List
? It is easy to accomplish this. Use the collector returned by the
toList()
method of the
Collectors
class, like so:
Map<Person.Gender, List<String>> namesByGender =
Person.persons()
.stream()
.collect(Collectors.groupingBy(Person::getGender,
Collectors.mapping(Person::getName, Collectors.toList())));
System.out.println(namesByGender);
{FEMALE=[Donna, Laynie], MALE=[Ken, Jeff, Chris, Li]}
Groups can be nested. Let's create a report that groups people by gender. Within each gender group, it creates
another group based on the month of their births and lists the names of the people born in this group. This is a very
simple computation to perform. You already know how to group people by gender. All you need to do is perform
another grouping on the values of the keys that is simply another collector obtained using the
groupingBy()
method
again. In this case, the value for a key in the map representing the top level grouping (by gender) is a
Map
. Listing 13-11
contains the complete code to accomplish this. The arguments to the
collect()
method are cluttered. You may use
static imports to import the static methods from the
Collectors
class to reduce the cluttering a bit. The program
assumes that every person has a date of birth.
Listing 13-11.
Using Nested Groupings
// NestedGroupings.java
package com.jdojo.streams;
import java.time.Month;
import java.util.Map;
import java.util.stream.Collectors;
public class NestedGroupings {
public static void main(String[] args) {
Map<Person.Gender, Map<Month, String>> personsByGenderAndDobMonth
= Person.persons()
.stream()
.collect(Collectors.groupingBy(Person::getGender,
Collectors.groupingBy(p -> p.getDob().getMonth(),
Collectors.mapping(Person::getName,
Collectors.joining(", ")))));
System.out.println(personsByGenderAndDobMonth);
}
}
{FEMALE={DECEMBER=Laynie, JULY=Donna}, MALE={DECEMBER=Chris, JULY=Jeff, MAY=Ken, Li}}