Java Reference
In-Depth Information
Suppose you want to get a list of names, grouping them by gender. You need to use the second version of the
groupingBy() method that lets you perform a reduction operation on the values of each key. Notice that the type of
the second argument is Collector . The Collectors class contains many methods that return a Collector that you
will be using as the second argument.
Let's try a simple case where you want to group people by gender and count the number of people in each group.
The counting() method of the Collectors class returns a Collector to count the number of elements in a stream.
The following snippet of code accomplishes this:
Map<Person.Gender, Long> countByGender =
Person.persons()
.stream()
.collect(Collectors.groupingBy(Person::getGender, Collectors.counting()));
System.out.println(countByGender);
{MALE=4, FEMALE=2}
Let's get back to the example of listing a person's name by gender. You need to use the mapping() method of the
Collectors class to get a collector that will map the list of people in the value of a key to their names and join them.
The signature of the mapping() method is
mapping(Function<? super T,? extends U> mapper, Collector<?
super U,A,R> downstream)
Notice the type of the second argument of the mapping() method. It is another Collector . This is where dealing
with grouping data gets complex. You need to nest collectors inside collectors. To simplify the grouping process, you
break down the things you want to perform on the data. You have already grouped people by their gender. The value
of the each key in the map was a List<Person> . Now you want to reduce the List<Person> to a String that contains
a comma-separated list of all people in the list. You need to think about this operation separately to avoid confusion.
You can accomplish this reduction as follows:
Use a function to map each person to his/her name. This function could be as simple as a
method reference like Person::getName . Think of the output of this step as a stream of person
names in a group.
What do you want to do with the stream of names generated in the first step? You may want to
collect them in a String , a List , a Set , or some other data structure. In this case, you want to
join the names of people, so you will use the collector returned from the joining() method of
the Collectors class.
The following snippet of code shows how to group the names of person by gender:
Map<Person.Gender, String> namesByGender =
Person.persons()
.stream()
.collect(Collectors.groupingBy(Person::getGender,
Collectors.mapping(Person::getName, Collectors.joining(", "))));
System.out.println(namesByGender);
{MALE=Ken, Jeff, Chris, Li, FEMALE=Donna, Laynie}
Search WWH ::




Custom Search