#概要
本記事はJava9から追加されたStreamクラスのiterateメソッドの第三引数でインクリメントした際の挙動についてまとめたものです。
#1.Streamクラスの入力引数を三つ持つiterateメソッドについて
Streamクラスの入力引数を三つ持つiterateメソッドの使い方として、以下のようなコードで紹介されるのをよくお見かけします。
// 0~9までの数値を出力するコード
Stream.iterate(0, i -> i < 10, i -> i + 1).forEach(System.out::println);
0
1
2
3
4
5
6
7
8
9
iterateメソッドの引数はそれぞれ以下の通りです。
第一引数:初期値
第二引数:次のStreamの要素を返すための条件を返却するクラス(サンプルコード上はラムダ式で記載)
第三引数:次のStreamの要素を返却するクラス(サンプルコード上はラムダ式で記載)
従来のfor文に書き直すと以下のようになります。
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
初めて知った当時はStream APIでfor文ライクなものが使えると感動しました。
JavaのAPIドキュメントは以下のリンク先です。
JavaのAPIドキュメントよりStream.iterateの仕様
#2.第三引数でのインクリメント
第三引数についてインクリメントを使わずにi->i+1でよく説明されることについて疑問に思い、以下のような記載をしました。
Stream.iterate(0, i -> i < 10, i -> i++).forEach(System.out::println);
すると実行結果は以下のようになりました。
0
0
0
0
0
0
0
0
~~~~~~~~~~~~~~~~~~~~~~
以下、延々と0が出力され続けるため省略
~~~~~~~~~~~~~~~~~~~~~~
i=0のまま結果が出力されることになり、無限ループが発生します。
Stream.classで第三引数に指定したUnaryOperatorクラスのapplyメソッド(サンプルコード上ではラムダ式で記載)を利用しているため、第三引数で値をインクリメントする前に返却してるのですね。
どうしてもインクリメントにしたい場合は以下のように後置から前置に書き直す必要があります。
Stream.iterate(0, i -> i < 10, i -> ++i).forEach(System.out::println);
#おわりに
インクリメントについてこのような特徴があるから紹介するときはi->i+1で書いてるのかもしれませんね。
個人的に書く場合はインクリメント使いそうです。
そもそも私は9以降のJavaについて個人でしか使ってませんが……