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

后端 未结 9 1507
难免孤独
难免孤独 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

    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 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...

提交回复
热议问题