遅延評価、並列処理

Streamはラムダ式を使って関数型言語のようなスタイルで操作することができるため、従来のコレクションを操作するために使っても便利だが、遅延評価可能なコレクションという特徴も持っている。そのため、例えば以下のように無限に値を返すジェネレータをStreamで作成することもできる。

// 10、20、40、80…と無限に値を返すStreamを生成
Stream<Integer> stream = Stream.iterate(10, i -> i * 2);
// 先頭の5件のみ表示
stream.limit(5).forEach(System.out::println);

また、以下のようにして並列処理が可能なStreamを生成することもできる。並列処理可能なStreamではmap()やfilter()などのメソッドでの各要素に対する処理が自動的に並列に実行されるため、処理の高速化が期待できる。

ただし通常のStreamでは各要素に対する処理は要素の格納順に行われるが、並列処理可能なStreamでは要素の格納順と処理の順番がバラバラになるという点に注意が必要だ。

// Listから並列処理可能なStreamを取得する
List<String> list = Arrays.asList("Java", "Groovy", "Scala");
list.parallelStream()
  .map(s -> s.toUpperCase())
  .forEach(System.out::println);

// Streamから並列処理可能なStreamを取得する
IntStream.range(1, 100)
  .parallel()
  .filter(i -> i % 2 == 0)
  .forEach(System.out::println);

なお、並列処理可能なStreamに対してsequential()メソッドを呼び出すことでシーケンシャルに処理が実行される通常のStreamを取得することができる。