将一个系列分成两个不同的系列的最佳方法是什么?

use*_*966 36 java filter java-8 data-partitioning java-stream

我有一组数字:

 Set<Integer> mySet = [ 1,2,3,4,5,6,7,8,9]
Run Code Online (Sandbox Code Playgroud)

我想把它分成两组赔率和赔率.

我的方法是使用过滤器两次:

Set<Integer> set1 = mySet.stream().filter(y -> y % 2 == 0).collect(Collectors.toSet())
Set<Integer> set2 =mySet.stream().filter(y -> y % 2 != 0).collect(Collectors.toSet())
Run Code Online (Sandbox Code Playgroud)

我不喜欢这个解决方案,因为我经历了整套两次.

有没有更聪明的方法呢?

And*_*ner 39

Map<Boolean, List<Integer>> partitioned = 
    set.stream().collect(Collectors.partitioningBy(x -> x%2 == 0));
Run Code Online (Sandbox Code Playgroud)

元素partitioned.get(true)是均匀的; 元素partitioned.get(false)是奇数.

与使用此功能不同groupingBy,即使它们是空的,也可以保证地图truefalse列表都会出现在地图中.(没有在Java 8中记录,但确实如此; Java 9的doc现在明确说明了它).

  • @JeffC不,`collect`调用会将原始集合拆分为两个列表,一个是"true",另一个是"false".真正的列表是偶数元素,错误列表是奇数元素.调用`partitioned.get(true)`只返回`collect`创建的"true"列表 (4认同)
  • @JeffC,据我所知OPs问题,OP关注两次调用过滤,因为两次调用都会迭代整个集合.Andy的答案只会迭代一次,将其分成两组. (3认同)

RAZ*_*Taz 13

简单循环和if/else将是一个简洁的解决方案

Set<Integer> setEven = new HashSet<>();
Set<Integer> setOdd = new HashSet<>();

for (Integer val : mySet) {
    if (val % 2 == 0)
        setEven.add(val);
    else
        setOdd.add(val);
}
Run Code Online (Sandbox Code Playgroud)

或者使用三元运算符可以更好地简化代码

for(Integer val : mySet) {
    ((val % 2 == 0) ? setEven : setOdd).add(val);
}
Run Code Online (Sandbox Code Playgroud)

  • -1以这种方式使用条件表达式(但实际上并没有使用downvoting):你必须引入一个无意义的变量,因为它并不意味着像这样使用.坚持使用if/else.如果你真的想要使用条件表达式,请执行`((val%2 == 0)?setEven:setOdd).add(val);`. (9认同)

Ami*_*era 13

你可以使用Collectors#partitioningBy如下.

Map<Boolean,List<Integer>> evenOddMap  = mySet.stream().collect(Collectors.partitioningBy(e -> e % 2 == 0));
System.out.println("Even : "+evenOddMap.get(true));
System.out.println("Odd : "+evenOddMap.get(false));
Run Code Online (Sandbox Code Playgroud)


tso*_*akp 11

你可以使用Collectors.partitioningBy:

        Map< Boolean, Set<Integer> > map =
        mySet.stream().collect( Collectors.partitioningBy( y -> y % 2 == 0, 
        Collectors.toSet() ) );

        Set<Integer> odds = map.get(Boolean.TRUE);
        Set<Integer> evens = map.get(Boolean.FALSE);
Run Code Online (Sandbox Code Playgroud)

编辑:

我看到有几个类似的答案.这里的细微差别在于它显示了如何获取集合Set而不是List,以防OP想要这样.