Based on the following answer: https://stackoverflow.com/a/30202075/8760211
How to sort each group by stud_id and then return a List with all Students as result of the g
try sort first and then groupinBy it works well. The below code sorts the Students within the location.
students.stream().sorted().collect(Collectors.groupingBy(Student::getLocation))
The output in this case is
{New York=[1726 John New York, 3442 Mark New York, 5223 Michael New York], Los Angeles=[2234 Andrew Los Angeles], California=[4321 Max California, 7765 Sam California]}
If you would like to have locations also to be sorted, use a code snippet like below
students.stream().sorted().collect(Collectors.groupingBy(Student::getLocation, TreeMap::new, Collectors.toList()))
The output in this case is
{California=[4321 Max California, 7765 Sam California], Los Angeles=[2234 Andrew Los Angeles], New York=[1726 John New York, 3442 Mark New York, 5223 Michael New York]}
Student class implements Comparable and the compareTo method is is based on the id.
First, about sorting within each group. Collectors.groupingBy
has a second variant which allows you to specify a collector which is used to generate the groups. The collector you specify can be one which collects the items in a sorted way (e.g. a TreeSet
), and as a finishing operation transforms it to a sorted list. Such a collector can be created with Collectors.collectingAndThen()
.
For example, with Integers I tried:
List<Integer> list = Arrays.asList(9, 2, 43, 6, 5, 3, 87, 56, 87, 67, 77, 22, 23, 1);
System.out.println(
list.stream().collect(Collectors.groupingBy(
i -> i % 3, // classifier
Collectors.collectingAndThen(
Collectors.toCollection(() -> new TreeSet<>()), // intermediate collector
set -> new ArrayList<>(set))))); // finishing operation
Output:
{0=[3, 6, 9, 87], 1=[1, 22, 43, 67], 2=[2, 5, 23, 56, 77]}
I'm sure you manage to translate this to your case. You might need to create a TreeSet
with a custom comparator so that the students in each group are ordered the way you want, or, if students are sorted in the same way always, make Student
implement Comparable
.
Second about sorting the groups. Collectors.groupingBy
by default creates a HashMap
, which does not have a specified order of the keys (above, the keys are ordered correctly by chance). So, to also order the keys, you need to use the Collectors.groupingBy
variant which also lets you create the result map, which luckily also exists:
System.out.println(
list.stream().collect(Collectors.groupingBy(
i -> i % 3, // classifier
new TreeMap<>((a, b) -> b.compareTo(a)), // map creator
Collectors.collectingAndThen(
Collectors.toCollection(() -> new TreeSet<>()), // intermediate collector
set -> new ArrayList<>(set))))); // finishing operation
I specified a custom comparator for the map to show that the ordering is indeed different. The result is:
{2=[2, 5, 23, 56, 77], 1=[1, 22, 43, 67], 0=[3, 6, 9, 87]}
Now, whether this is more readable and maintainable than a good-old pre-Java 8 solution is a matter of taste...
I was facing same issue and I tried all the solutions but not able to fix the problem, Then I tried following way and finally I am able to fix my problem.
In above example my
studlist
was already sorted but still its generating map in any order that was main question.
Map<String, List<Student>> studlistGrouped =
studlist.stream().collect(Collectors.groupingBy(w -> w.stud_location));
**studlistGrouped = new TreeMap<String, List<Student>>(studlistGrouped);**
So using this above solution it sorted all the keys in Map. Our goal to get result into Map only then why people try to converting it into list?