我有一个整数输入,我想将所有偶数按升序排列在所有奇数之前,并保留赔率顺序。我非常确定我可以通过收集器和/或下游收集器实现这一目标,但我不确定如何做到这一点。我想知道如何对错误列表进行排序,这样如果可能的话我可以在一行中实现它。因此,在分组之后,我希望将错误列表按升序排序,而另一个(真实赔率列表)保持不变,并且在转换之后能够将它们平面映射到一个列表中。
示例:
输入为:
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
你实际上并不需要分组。如果流是有序的,则
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());
使用
groupingBy
的过载,需要下游收集器
例如:
groupingBy(
integer -> integer % 2 != 0,
collectingAndThen(
toList(),
list -> list.stream().sorted().collect(toList()))
为了使用 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);