Java收集器按分组

Java收集器按分组,java,dictionary,stream,collectors,groupingby,Java,Dictionary,Stream,Collectors,Groupingby,我有一个整数输入,我想把所有偶数按升序排列在所有奇数之前,并保留赔率顺序。我很确定我可以通过收集器和/或下游收集器实现这一点,但我不确定如何做到这一点。我想知道如何对错误列表进行排序,以便尽可能在一行中实现它。因此,在通过分组之后,我希望将错误列表按升序排序,而另一个(真正的赔率列表)保持不变,并且在转换之后,能够将它们平面映射到一个列表中 例如: Stream.of(3, 6, 2, 1, 4, 5).sorted( Comparator.<Integer>comparin

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

例如:

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);
输入为:

1 6 2 3 4 5
这一行条目应为:

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

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

2 4 6 1 3 5

使用
groupingBy
的重载

例如:

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

你实际上不需要分组。如果流是有序的,
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);
如果您想要一个
映射
,则可以按奇偶校验进行分区(这将保证
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());
Map partitions=Stream.of(3,6,2,1,4,5)。收集(
//收集到ArrayList以确保它是可变的
收集器.partitionBy(x->x%2!=0,收集器.toCollection(ArrayList::new))
);
partitions.get(false).sort(Comparator.naturalOrder());

用于使用
收集器以复杂方式解决简单问题的唯一乐趣。teeing
在Java 12及更高版本中提供:

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);
List List=List.of(3,6,2,1,4,5);
列表结果=
list.stream()
收集(
Collectors.filtering(i->i%2==0,Collectors.toList()),
Collectors.filtering(i->i%2!=0,Collectors.toList()),
(列出偶数,列出赔率)->{
列表合并=新建ArrayList();
evens.sort(Comparator.naturalOrder());
合并。添加所有(evens);
合并。全部(赔率);
返回合并;
}
));
系统输出打印项次(结果);

您真的希望它们单独收藏,还是按顺序排列,然后按顺序排列?如果是后者,
list.sort(Comparator.comparing(i->i%2!=0)。那么comparingit(i->i))
就足够了。谢谢,但这并不保留赔率的顺序。它对所有列表进行排序。我只想对我的情况中的错误列表进行排序。1234563{false=[2,4,6],true=[1,3,5,3]},但我得到1234563{false=[2,4,6],true=[1,3,3,5]}@UnknowError.1234563应该对evens->246进行排序并保留赔率的顺序,这有点奇怪
list->(list.get(0)%2!=0)?list:list.stream().sorted().collect(toList())
。非常感谢Andy。考虑到当前的逻辑,这是正确的。get(0)将非常适合,因为列表将始终分为两组。谢谢,工作方式与我预期的一样。给定的语法Comparator.ComparingIT对我来说有点奇怪,因为我们有整数流,如果我使用Comparator.ComparingIT(我的逻辑),它会抱怨。@unknownerror是的,它无法推断泛型类型,所以我必须显式指定它。如果您不喜欢奇怪的语法,您可以先声明一个类型为
Comparator
的局部变量,然后将其传递给
sorted
。谢谢您的解决方案。你是对的,这就像用原子弹杀死蟑螂一样。然而,收藏家似乎是非常强大的功能,这是非常误解的大多数人,包括我。
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());
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);