【问题标题】:Java Collectors Grouping ByJava 收集器分组依据
【发布时间】:2021-07-23 19:29:02
【问题描述】:

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

例子:

输入是:

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

【问题讨论】:

  • 您真的希望它们在单独的集合中,还是按顺序排列偶数,然后按顺序排列赔率?如果是后者,list.sort(Comparator.comparing(i -&gt; i % 2 != 0).thenComparingInt(i -&gt; i)) 就足够了。

标签: java dictionary stream collectors groupingby


【解决方案1】:

使用groupingBy的重载,其中takes a downstream collector

例如:

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

【讨论】:

  • 谢谢,但这不会保留赔率的顺序。它对所有列表进行排序。在我的情况下,我只想对错误列表进行排序。 1 2 3 4 5 6 3 {false=[2, 4, 6], true=[1, 3, 5, 3]},但我得到 1 2 3 4 5 6 3 {false=[2, 4, 6 ], true=[1, 3, 3, 5]}
  • @unknownerror works fine here.
  • 1 2 3 4 5 6 3 应该对偶数进行排序 -> 2 4 6 并保留赔率的顺序 1 3 5 3,这有点时髦
  • list -&gt; (list.get(0) % 2 != 0) ? list : list.stream().sorted().collect(toList()).
【解决方案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&lt;Boolean, List&lt;Integer&gt;&gt;,你可以通过奇偶校验分区(这将保证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());

【讨论】:

  • 谢谢,按我的预期工作。考虑到我们有整数流这一事实,给定的语法 Comparator.comparingInt 对我来说有点奇怪,如果我这样做 Comparator.comparingInt(my logic) 它就会抱怨。
  • @unknownerror 是的,它无法推断出泛型类型,所以我必须明确指定它。如果你不喜欢奇怪的语法,你可以先声明一个Comparator&lt;Integer&gt; 类型的局部变量,然后将它传递给sorted
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 2021-03-14
    • 2019-04-29
    • 2019-09-03
    • 1970-01-01
    • 2016-01-25
    • 2020-09-02
    • 1970-01-01
    • 1970-01-01
    • 2021-11-14
    相关资源
    最近更新 更多