甲集电极可以用于此目的。
- 对于两个类别,请使用
Collectors.partitioningBy()
工厂。
这将创建Map
从Boolean
到的List
条目,并根据条目将项目放在一个或另一个列表中Predicate
。
注意:由于流需要全部消耗掉,因此无法在无限流上使用。而且由于无论如何都会消耗流,因此此方法只是将它们放入列表中,而不是创建新的带内存流。如果需要流作为输出,则始终可以流式处理这些列表。
另外,甚至在您提供的仅heads示例中也不需要迭代器。
Random r = new Random();
Map<Boolean, List<String>> groups = stream
.collect(Collectors.partitioningBy(x -> r.nextBoolean()));
System.out.println(groups.get(false).size());
System.out.println(groups.get(true).size());
- 有关更多类别,请使用
Collectors.groupingBy()
工厂。
Map<Object, List<String>> groups = stream
.collect(Collectors.groupingBy(x -> r.nextInt(3)));
System.out.println(groups.get(0).size());
System.out.println(groups.get(1).size());
System.out.println(groups.get(2).size());
如果流不是Stream
,而是原始流之一(例如)IntStream
,则此.collect(Collectors)
方法不可用。您必须在没有收集器工厂的情况下以手动方式进行操作。它的实现如下所示:
[自2020-04-16起的示例2.0]
IntStream intStream = IntStream.iterate(0, i -> i + 1).limit(100000).parallel();
IntPredicate predicate = ignored -> r.nextBoolean();
Map<Boolean, List<Integer>> groups = intStream.collect(
() -> Map.of(false, new ArrayList<>(100000),
true , new ArrayList<>(100000)),
(map, value) -> map.get(predicate.test(value)).add(value),
(map1, map2) -> {
map1.get(false).addAll(map2.get(false));
map1.get(true ).addAll(map2.get(true ));
});
在此示例中,我使用初始集合的完整大小初始化ArrayList(如果完全知道的话)。即使在最坏的情况下,这也可以防止调整大小事件,但有可能吞噬2 * N * T空间(N =元素的初始数量,T =线程数)。要权衡速度,您可以不使用它,也可以使用受过良好教育的猜测,例如一个分区中预期的最大元素数(对于平衡的拆分,通常刚好超过N / 2)。
我希望我不会使用Java 9方法来冒犯任何人。对于Java 8版本,请查看编辑历史记录。
Stream
为Stream
s 的可能性上,尽管我认为达到此问题的人实际上正在寻求实现这一目标的方法,而不管这种约束如何,这是Mark的答案。这可能是由于标题中的问题与说明中的问题不同。