2

I have a list of people which I would like to group based on their age (group1 has age < 20, group2 has age >=20) and sort each group based on name and age using Java 8: List of people:

Group 1:

Ane 12
Col 14

Group 2:

James 24
thomas 34
Xavier 55

I would like to use Java 8 to do something like this:

list.stream().collect(Collectors.groupingBy(...
2
  • 1
    Do you want the groups sorted by name first or age first? Commented Nov 13, 2016 at 18:04
  • @akaliza is the question about splitting the list into two groups, or grouping them by multiple age ranges? If it's about grouping by age range, you could update your question for clarity (and to let me fix my answer proposal :)) Commented Nov 14, 2016 at 10:52

2 Answers 2

7

You can get to what you want by:

  • Sorting your whole collection of people by age (and then name).
  • Partitioning it.

Note that the order of each partition will be maintained:

import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.partitioningBy;

people.stream()
  .sorted(
     comparing(Person::getAge)
       .thenComparing(Person::getName))
  .collect(partitioningBy(p -> p.getAge() >= 20))

Thanks to Christoffer for his improvement proposal: Scandinavian Java must be as slick as a set of IKEA assembly instructions :)

Sign up to request clarification or add additional context in comments.

3 Comments

You should be using Comparator.comparing(Person::getAge).
Thanks, it's cleaner that way :)
Also, to make it even cleaner, import static java.util.Collectors.partitioningBy and import static java.util.Comparator.comparing;
2

You will want to use the partitioningBy collector instead. It will allow you to specify a predicate and return a map keyed by a boolean:

Map<Boolean, List<?>> partitioned = list.stream().sorted(...).collect(Collectors.partitioningBy(...));

7 Comments

what if I want people between age 20 and 50? can I chain partitioningBy?
Not really. In that case you'll need to write a function which returns a different value for each group, and then do a groupingBy with that function.
I understand, we have a predicate, therefore I can do this p -> p.getAge() >= 20 && p.getAge() <50
Ah, I thought you wanted three groups: a <20, a 20-50, and a >50. If you want one group of 20-50 and the other of everyone else, that will work.
Basically, yes.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.