Java 收集器分组依据

问题描述 投票:0回答:3

我有一个整数输入,我想将所有偶数按升序排列在所有奇数之前,并保留赔率顺序。我非常确定我可以通过收集器和/或下游收集器实现这一目标,但我不确定如何做到这一点。我想知道如何对错误列表进行排序,这样如果可能的话我可以在一行中实现它。因此,在分组之后,我希望将错误列表按升序排序,而另一个(真实赔率列表)保持不变,并且在转换之后能够将它们平面映射到一个列表中。

示例:

输入为:

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);

上面代码的输出是:

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

这行条目应变为:

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

转换后。

输出应该是偶数,位于赔率之前,并按升序排序,同时保留赔率的顺序,如下所示:

2 4 6 1 3 5
java dictionary stream collectors groupingby
3个回答
2
投票

你实际上并不需要分组。如果流是有序的,则

Stream.sorted
方法是一种稳定的排序。

您只需要一个比较器,例如:

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)

示例:

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);

打印:

2
4
6
3
1
5

如果您想要

Map<Boolean, List<Integer>>
,则可以按奇偶校验进行分区(这将保证
false
键始终存在于映射中),然后对与
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());

1
投票

使用

groupingBy
的过载,需要下游收集器

例如:

groupingBy(
    integer -> integer % 2 != 0,
    collectingAndThen(
        toList(),
        list -> list.stream().sorted().collect(toList()))

1
投票

为了使用 Java 12 及更高版本中提供的

Collectors.teeing
以复杂的方式解决简单问题的唯一乐趣:

List<Integer> list = List.of(3, 6, 2, 1, 4, 5);

List<Integer> result = 
    list.stream()
        .collect(Collectors.teeing(
                    Collectors.filtering(i -> i % 2 == 0, Collectors.toList()), 
                    Collectors.filtering(i -> i % 2 != 0, Collectors.toList()), 
                    (List<Integer> evens, List<Integer> odds) -> {
                        List<Integer> merged = new ArrayList<>();
                        evens.sort(Comparator.naturalOrder());
                        merged.addAll(evens);
                        merged.addAll(odds);
                        return merged;
                    }
        ));

System.out.println(result);
© www.soinside.com 2019 - 2024. All rights reserved.