StreamAPIについて調べてみた range編 その1

【前提条件】

[環境]
[参考資料]

Java8 APIドキュメント
Java Platform SE 8

【概要】

今回はIntStreamクラスとLongStreamクラスにある
rangeメソッドとrangeClosedメソッドについて調べてみました。

range/rangeClosedメソッドは
ある数値の範囲をStreamとして扱うものです。

【range/rangeClosedメソッドの使い方】

range/rangeClosedメソッドはstaticメソッドなので、
IntStream.rangeのようにすれば使えます。

戻り値はIntStream、LongStreamです。

    final int[] valArray1 = IntStream.range(0, 10).toArray();
    final int[] valArray2 = IntStream.rangeClosed(0, 10).toArray();
    final long[] valArray3 = LongStream.range(0, 10).toArray();
    final long[] valArray4 = LongStream.rangeClosed(0, 10).toArray();

最初の引数に初期値、二番目の引数に終了値を渡します。

【range/rangeClosedメソッドの違い】

二つのメソッドの違いは取得できる範囲が異なることです。

[サンプルコード]
    public static void main(final String[] args) {

        System.out.print("IntStream#ragnge : ");
        IntStream.range(0, 10).forEach(System.out::print);
        System.out.print("\r\n");

        System.out.print("IntStream#rangeClosed : ");
        IntStream.rangeClosed(0, 10).forEach(System.out::print);
        System.out.print("\r\n");

        System.out.print("LongStream#ragnge : ");
        LongStream.range(0, 10).forEach(System.out::print);
        System.out.print("\r\n");

        System.out.print("LongStream#rangeClosed : ");
        LongStream.rangeClosed(0, 10).forEach(System.out::print);
        System.out.print("\r\n");
    }

それぞれrange/rangeClosedで生成したStraemにたいして
forEachでコンソールに出力しているサンプルです。

[出力結果]
IntStream#ragnge : 0123456789
IntStream#rangeClosed : 012345678910
LongStream#ragnge : 0123456789
LongStream#rangeClosed : 012345678910

rangeの場合は終了値を含まず、rangeClosedの場合は終了値を含みます。

    // range
    for (int i = 0; i < 10; i++) {}

    // rangeClosed
    for (int i = 0; i <= 10; i++) {}

と言うイメージです。

【for文の置き換え】

ということでfor文でカウンタ変数などを初期化するやり方を
range/rangeClosedで置き換えてみます。

    public static void main(final String[] args) {

        for (int i = 1; i <= 9; i++) {

            for (int j = 1 ; j <= 9; j++) {

                final int val = i * j;
                System.out.println(i + " × " + j + " = " + val);
            }
        }

        IntStream.rangeClosed(1, 9).forEach(i -> {

            IntStream.rangeClosed(1, 9).forEach(j -> {

                final int val = i * j;
                //i++;
                System.out.println(i + " × " + j + " = " + val);
            });
        });
    }

これで同じ結果が得られます。
range/rangeClosedメソッドを使ったほうが一行に書く量は増えていますが、
IDEで補完できるのでそんなに手間でもないと思います。

カウント変数を使うような処理で並列化させることはないと思うので、
並列化させるメリットはありませんが、
内部イテレータの外にある変数を変更できないのはメリットになるかと思います。

【まとめ】

range/rangeClosedを使ったほうが副作用は少なくできそうかなと言う印象です。
ミュータブルなオブジェクトだった場合は効果はありませんが・・・

場合によって適宜使い分けましょうと言う結論ですかね。