Group by a Collection attribute using Java Streams
Clash Royale CLAN TAG#URR8PPP
up vote
9
down vote
favorite
I have an object that contains a Collection of strings, let's say the languages that a person speaks.
public class Person
private String name;
private int age;
private List<String> languagesSpoken;
// ...
Now, creating some instances like this...
Person p1 = new Person("Bob", 21, Arrays.asList("English", "French", "German"));
Person p2 = new Person("Alice", 33, Arrays.asList("English", "Chinese", Spanish"));
Person p3 = new Person("Joe", 43, Arrays.asList("English", "Dutch", "Spanish", "German"));
//put them in list
List<Person> people = Arrays.asList(p1,p2,p3);
... what I want to have is a Map<String, List<Person>>
, for every language listing the persons that speak the language:
["English" -> [Bob object, Alice object, Joe object],
"German" -> [Bob object, Joe object],
etc. ]
Of course this can be programmed easily in an imperative way, but how to do it the functional way with Java Streams? I have tried something like people.stream.collect(groupingBy(Person::getLanguagesSpoken))
but that of course gives me a Map<List<String>, List<Person>>
. All the examples I could find, are using groupingBy
on Primitives or Strings.
java java-8 java-stream
add a comment |Â
up vote
9
down vote
favorite
I have an object that contains a Collection of strings, let's say the languages that a person speaks.
public class Person
private String name;
private int age;
private List<String> languagesSpoken;
// ...
Now, creating some instances like this...
Person p1 = new Person("Bob", 21, Arrays.asList("English", "French", "German"));
Person p2 = new Person("Alice", 33, Arrays.asList("English", "Chinese", Spanish"));
Person p3 = new Person("Joe", 43, Arrays.asList("English", "Dutch", "Spanish", "German"));
//put them in list
List<Person> people = Arrays.asList(p1,p2,p3);
... what I want to have is a Map<String, List<Person>>
, for every language listing the persons that speak the language:
["English" -> [Bob object, Alice object, Joe object],
"German" -> [Bob object, Joe object],
etc. ]
Of course this can be programmed easily in an imperative way, but how to do it the functional way with Java Streams? I have tried something like people.stream.collect(groupingBy(Person::getLanguagesSpoken))
but that of course gives me a Map<List<String>, List<Person>>
. All the examples I could find, are using groupingBy
on Primitives or Strings.
java java-8 java-stream
add a comment |Â
up vote
9
down vote
favorite
up vote
9
down vote
favorite
I have an object that contains a Collection of strings, let's say the languages that a person speaks.
public class Person
private String name;
private int age;
private List<String> languagesSpoken;
// ...
Now, creating some instances like this...
Person p1 = new Person("Bob", 21, Arrays.asList("English", "French", "German"));
Person p2 = new Person("Alice", 33, Arrays.asList("English", "Chinese", Spanish"));
Person p3 = new Person("Joe", 43, Arrays.asList("English", "Dutch", "Spanish", "German"));
//put them in list
List<Person> people = Arrays.asList(p1,p2,p3);
... what I want to have is a Map<String, List<Person>>
, for every language listing the persons that speak the language:
["English" -> [Bob object, Alice object, Joe object],
"German" -> [Bob object, Joe object],
etc. ]
Of course this can be programmed easily in an imperative way, but how to do it the functional way with Java Streams? I have tried something like people.stream.collect(groupingBy(Person::getLanguagesSpoken))
but that of course gives me a Map<List<String>, List<Person>>
. All the examples I could find, are using groupingBy
on Primitives or Strings.
java java-8 java-stream
I have an object that contains a Collection of strings, let's say the languages that a person speaks.
public class Person
private String name;
private int age;
private List<String> languagesSpoken;
// ...
Now, creating some instances like this...
Person p1 = new Person("Bob", 21, Arrays.asList("English", "French", "German"));
Person p2 = new Person("Alice", 33, Arrays.asList("English", "Chinese", Spanish"));
Person p3 = new Person("Joe", 43, Arrays.asList("English", "Dutch", "Spanish", "German"));
//put them in list
List<Person> people = Arrays.asList(p1,p2,p3);
... what I want to have is a Map<String, List<Person>>
, for every language listing the persons that speak the language:
["English" -> [Bob object, Alice object, Joe object],
"German" -> [Bob object, Joe object],
etc. ]
Of course this can be programmed easily in an imperative way, but how to do it the functional way with Java Streams? I have tried something like people.stream.collect(groupingBy(Person::getLanguagesSpoken))
but that of course gives me a Map<List<String>, List<Person>>
. All the examples I could find, are using groupingBy
on Primitives or Strings.
java java-8 java-stream
java java-8 java-stream
asked 24 mins ago
user3579358
6313
6313
add a comment |Â
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
11
down vote
You can break the Person
instances into pairs of language and Person
(using flatMap
) and then group them as required:
Map<String, List<Person>> langPersons =
people.stream()
.flatMap(p -> p.getLanguagesSpoken()
.stream()
.map(l -> new SimpleEntry<>(l,p)))
.collect(Collectors.groupingBy(Map.Entry::getKey,
Collectors.mapping(Map.Entry::getValue,
Collectors.toList())));
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
11
down vote
You can break the Person
instances into pairs of language and Person
(using flatMap
) and then group them as required:
Map<String, List<Person>> langPersons =
people.stream()
.flatMap(p -> p.getLanguagesSpoken()
.stream()
.map(l -> new SimpleEntry<>(l,p)))
.collect(Collectors.groupingBy(Map.Entry::getKey,
Collectors.mapping(Map.Entry::getValue,
Collectors.toList())));
add a comment |Â
up vote
11
down vote
You can break the Person
instances into pairs of language and Person
(using flatMap
) and then group them as required:
Map<String, List<Person>> langPersons =
people.stream()
.flatMap(p -> p.getLanguagesSpoken()
.stream()
.map(l -> new SimpleEntry<>(l,p)))
.collect(Collectors.groupingBy(Map.Entry::getKey,
Collectors.mapping(Map.Entry::getValue,
Collectors.toList())));
add a comment |Â
up vote
11
down vote
up vote
11
down vote
You can break the Person
instances into pairs of language and Person
(using flatMap
) and then group them as required:
Map<String, List<Person>> langPersons =
people.stream()
.flatMap(p -> p.getLanguagesSpoken()
.stream()
.map(l -> new SimpleEntry<>(l,p)))
.collect(Collectors.groupingBy(Map.Entry::getKey,
Collectors.mapping(Map.Entry::getValue,
Collectors.toList())));
You can break the Person
instances into pairs of language and Person
(using flatMap
) and then group them as required:
Map<String, List<Person>> langPersons =
people.stream()
.flatMap(p -> p.getLanguagesSpoken()
.stream()
.map(l -> new SimpleEntry<>(l,p)))
.collect(Collectors.groupingBy(Map.Entry::getKey,
Collectors.mapping(Map.Entry::getValue,
Collectors.toList())));
edited 16 mins ago
answered 19 mins ago


Eran
268k35416503
268k35416503
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52984816%2fgroup-by-a-collection-attribute-using-java-streams%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password