Java 8, Lambda: Sorting within grouped Lists and merging all groups to a list

后端 未结 9 1309
难免孤独
难免孤独 2021-02-09 04:21

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

相关标签:
9条回答
  • 2021-02-09 04:52

    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.

    0 讨论(0)
  • 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...

    0 讨论(0)
  • 2021-02-09 05:01

    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?

    0 讨论(0)
提交回复
热议问题