2017-05-03 37 views
12

考虑下面的代码:如何通过使用Java 8的条件分隔列表中的流

List<Integer> odd = new ArrayList<Integer>(); 
List<Integer> even = null; 
List<Integer> myList = Arrays.asList(1,2,3,4,5,6,7,8,9,10); 
even = myList.stream() 
       .filter(item -> { 
        if(item%2 == 0) { return true;} 
        else { 
          odd.add(item); 
          return false; 
        } 
       }) 
       .collect(Collectors.toList()); 

我想在这里做的是从一个列表到单独列出得到偶数和奇数值。

filter()方法为偶数项返回true并且流收集器将收集它们。
对于奇怪的情况,过滤器将返回false,并且该物品将永远不会到达收集器。

因此,我在else块之前的另一个列表中添加了这样的奇数。

我知道这不是一个使用流的优雅方式。例如,如果我使用并行流,那么奇数列表将会出现线程安全问题。由于性能原因,我不能使用不同的过滤器多次运行它(应该是O(n))。

这只是一个用例的例子,该列表可能包含任何对象,并且过滤器内部的lambda需要根据某些逻辑将它们分离为单独的列表。

简而言之:从列表中创建包含基于某些条件分离的项目的多个列表。

没有流它只是运行一个for循环,并做简单的if-else并根据条件收集项目。

+8

看着'Collectors.groupingBy' /'Collectors.partitioningBy' –

+0

'Potenually answers by http://stackoverflow.com/questions/19940319/can-you-split-a-stream-into-twostreams –

+7

'item/2 == 0'不会分隔偶数和奇数。你需要'项目%2 == 0' –

回答

22

这里是你怎么可以分开的,即使这个列表的元素(数字)和奇数的例子:

List<Integer> myList = Arrays.asList(1,2,3,4,5,6,7,8,9,10); 

Map<Boolean, List<Integer>> evenAndOdds = myList.stream() 
     .collect(partitioningBy(i -> i % 2 == 0)); 

你会得到这样的偶/奇号码清单(或列表可能为空):

List<Integer> even = evenAndOdds.get(true); 
List<Integer> odd = evenAndOdds.get(false); 

您可以在partitioningBy中传递任何具有所需逻辑的lambda。

+9

按条件分组时,可以使用'partitioningBy'来代替。除了稍微更有效的可能性之外,它总是在'Map'中有'true'和'false'的结果,即如果没有元素落入该组中,而不是'null',则为空列表。 – Holger

+0

@霍尔感谢您的见解,更新的答案。空列表vs null是一个非常有用的功能,我没有意识到这一点,从文档中也不明显。 –

+7

这是一个已经被识别并[在Java 9中修复]的文档缺陷(http://download.java.net/java/jdk9/docs/api/java/util/stream/Collectors.html#partitioningBy-java。 util.function.Predicate-)。 – Holger

相关问题