I have a List<Person>
. With Java streams I can group the persons by last name using something like this:
Map<String, List<Person>> persons.stream()
.collect(Collectors.groupingBy(Person::getLastName));
But what if I want to group the first name of the persons by the last names? In other words, grouped by last name "Smith" I might have a list of "Jane" and "John". Is there maybe a value extractor version of groupingBy()
I can use? I'm thinking something like this:
Map<String, List<String>> persons.stream()
.collect(Collectors.groupingBy(Person::getLastName, Person::getFirstName));
Try use Collectors.mapping()
as a downstream collector within the Collectors.groupingBy()
method:
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
class Main {
public static void main(String[] args) {
List<Person> persons = List.of(
new Person("Smith", "John"),
new Person("Doe", "Jane"),
new Person("Smith", "Alex"),
new Person("Doe", "John"),
new Person("Brown", "Charlie")
);
Map<String, List<String>> groupedByLastName = persons.stream()
.collect(Collectors.groupingBy(
Person::getLastName,
Collectors.mapping(Person::getFirstName, Collectors.toList())
));
System.out.println(groupedByLastName);
}
}
class Person {
private String lastName;
private String firstName;
public Person(String lastName, String firstName) {
this.lastName = lastName;
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public String getFirstName() {
return firstName;
}
@Override
public String toString() {
return "Person{lastName='" + lastName + "', firstName='" + firstName + "'}";
}
}
Output:
{Brown=[Charlie], Smith=[John, Alex], Doe=[Jane, John]}