APIリファレンスを見ると、

ストリーム・パイプラインは順次、並列のいずれかで実行できます。この実行モードは、ストリームのプロパティの1つです。ストリームの作成時には、順次実行または並列実行の初期選択が行われます。(たとえば、Collection.stream()では順次ストリームが作成され、Collection.parallelStream()では並列ストリームが作成されます。)

Stream (Java Platform SE 8 )

と書いてあるけどよくわからないのでサンプルを書く。

今回の環境: Mac OS X Yosemite


$ uname -mrsv
Darwin 14.3.0 Darwin Kernel Version 14.3.0: Mon Mar 23 11:59:05 PDT 2015; root:xnu-2782.20.48~5/RELEASE_X86_64 x86_64

$ java -version
java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)

サンプルコード。数値のリストを順次処理と並列処理してみる。


import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class Sample{

  public static void main(String[] args){

    test_stream();
    test_parallelStream();
  }

  // 2乗の値を返す
  private static int square(int x){
    // 数値を標準出力へ
    System.out.println("number: " + x);
    return x * x;
  }

  private static void test_stream(){

    final List<Integer> numbers =
      Arrays.asList(1, 2, 3, 4, 5);

    // 順次処理のストリームを生成
    System.out.println("create stream");
    Stream<Integer> squares = 
      numbers.stream()
             .map(x -> square(x));

    // 2乗した値を標準出力へ
    System.out.println("output");
    squares.forEach((s) -> System.out.println("square: " + s));

    System.out.println();
  }

  private static void test_parallelStream(){

    final List<Integer> numbers =
      Arrays.asList(1, 2, 3, 4, 5);

    // 並列処理のストリームを生成
    System.out.println("create parallel stream");
    Stream<Integer> squares = 
      numbers.parallelStream()
             .map(x -> square(x));

    // 2乗した値を標準出力へ
    System.out.println("output");
    squares.forEach((s) -> System.out.println("square: " + s));

    System.out.println();
  }
}

実行結果。並列処理のほうは、元の数値のリスト通りに処理されていないことがわかる (並列処理なので出力される順番はデタラメになる)。


$ java Sample
create stream
output
number: 1
square: 1
number: 2
square: 4
number: 3
square: 9
number: 4
square: 16
number: 5
square: 25

create parallel stream
output
number: 3
square: 9
number: 5
square: 25
number: 2
square: 4
number: 4
square: 16
number: 1
square: 1

もうひとつわかることは、順次処理でも並列処理でも、 map メソッドに指定された関数 (ここでは square メソッド) をすぐには処理をしていないこと。

必要になってから実行をするという、遅延評価がここで使われている (ここでは Stream.forEach() メソッドをコールしたときに square の処理が実行されている)。

tags: java

Posted by NI-Lab. (@nilab)