Skip to content
Advertisement

Java Collectors Grouping By

I have an input of integers and I would like to sort all even numbers before all odd ones in ascending order and preserve the odds order. I am pretty sure I can achieve that with collectors and/or downstream collectors, but I am not sure how to do it. I would like to know how can I sort the false list, so I can achieve it in one line if possible. So after the grouping by I want to have the false list sorted in ascending and the other one (the true list of odds) to remain the same and after this conversion to be able to flatmap them into one list.

Example:

Input is:

1 6 2 3 4 5
Map<Boolean, List<Integer>> collect = Arrays
        .stream(bf.readLine().split("\s+"))
        .map(Integer::parseInt)
        .collect(Collectors.groupingBy(integer -> integer % 2 != 0));

System.out.println(collect);

The output of the code above is:

{false=[6, 2, 4], true=[1, 3, 5]}

This line of entries should become:

{false=[2, 4, 6], true=[1, 3, 5]}

after the conversion.

Output should be evens to come before the odds and to be sorted in ascending order and to preserve the order of the odds at the same time, like this:

2 4 6 1 3 5

Advertisement

Answer

You don’t actually need to group by. The Stream.sorted method is a stable sort if the stream is ordered.

You just need a comparator such as:

Comparator.comparingInt(x -> x % 2)
    // if it is even, order by natural order, otherwise they are "equal", so we map to a constant
    .thenComparingInt(x -> x % 2 == 0 ? x : 0)

Example:

Stream.of(3, 6, 2, 1, 4, 5).sorted(
    Comparator.<Integer>comparingInt(x -> x % 2)
        .thenComparingInt(x -> x % 2 == 0 ? x : 0))
    .forEachOrdered(System.out::println);

Prints:

2
4
6
3
1
5

If you want a Map<Boolean, List<Integer>> instead, you can partition by the parity (this will guarantee that the false key always exist in the map), and then sort the list associated with false:

Map<Boolean, List<Integer>> partitions = Stream.of(3, 6, 2, 1, 4, 5).collect(
    // collects to ArrayList to guarantee that it is mutable
    Collectors.partitioningBy(x -> x % 2 != 0, Collectors.toCollection(ArrayList::new))
);
partitions.get(false).sort(Comparator.naturalOrder());
User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement