これにはコレクターを使用できます。
- 2 つのカテゴリの場合は、
Collectors.partitioningBy()
factory を使用します。
これにより が作成Map<Boolean, List>
され、 に基づいていずれかのリストにアイテムが配置されますPredicate
。
注: ストリームは全体を消費する必要があるため、これは無限ストリームでは機能しません。いずれにせよストリームは消費されるため、このメソッドは、メモリを使用する新しいストリームを作成する代わりに、単純にそれらをリストに入れます。出力としてストリームが必要な場合は、これらのリストをいつでもストリーミングできます。
また、あなたが提供したヘッドのみの例でさえ、イテレータは必要ありません。
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
、 のようなプリミティブ ストリームの 1 つである場合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 ));
});
この例では、初期コレクションのフル サイズで ArrayLists を初期化します (これがわかっている場合)。これにより、最悪のシナリオでもサイズ変更イベントが発生しなくなりますが、2 N T スペース (N = 初期要素数、T = スレッド数) を消費する可能性があります。スペースと速度をトレードオフするには、スペースを除外するか、1 つのパーティションで予想される要素の最大数 (通常、バランスの取れた分割の場合は N/2 をわずかに超える) など、経験に基づいた最善の推測を使用できます。
Java 9 メソッドを使用して誰かを怒らせないことを願っています。Java 8 バージョンについては、編集履歴を参照してください。