Stream.iterate(Java 9 の変化) — シーケンス生成
Java 8 から導入された Stream.iterate は「初期値から次の値を生成していく」ための便利なメソッドです。
Java 9 で 終了条件を指定できるオーバーロード が追加され、無限ストリームを安全に有限化できるようになりました。
基本の仕組み
- Java 8 の iterate:
Stream.iterate(seed, unaryOperator)- 初期値
seedから始め、unaryOperatorを繰り返し適用して次の値を生成。 - 無限ストリームになるので、必ず
limitなどで有限化する必要がある。
- 初期値
- Java 9 の iterate(終了条件付き):
Stream.iterate(seed, hasNextPredicate, unaryOperator)hasNextPredicateで「続けるかどうか」を判定できる。- 終了条件を組み込めるので、
limitを使わずに有限ストリームを作れる。
基本コード例
Java 8 スタイル(無限 → limit)
Stream<Integer> s = Stream.iterate(1, n -> n + 1); // 1,2,3,4,...
List<Integer> list = s.limit(5).toList();
System.out.println(list); // [1, 2, 3, 4, 5]
JavaJava 9 スタイル(終了条件付き)
Stream<Integer> s = Stream.iterate(1, n -> n <= 5, n -> n + 1);
List<Integer> list = s.toList();
System.out.println(list); // [1, 2, 3, 4, 5]
Java例題で理解する
例題1: フィボナッチ数列(Java 8 スタイル)
Stream.iterate(new int[]{0,1}, a -> new int[]{a[1], a[0]+a[1]})
.limit(10)
.map(a -> a[0])
.forEach(System.out::println);
// 0 1 1 2 3 5 8 13 21 34
Java- ポイント: 配列で「前の値・次の値」を保持しながら生成。
例題2: 1〜100 の偶数(Java 9 スタイル)
Stream<Integer> evens = Stream.iterate(2, n -> n <= 100, n -> n + 2);
evens.forEach(System.out::println);
Java- ポイント: 終了条件を指定できるので limit 不要。
例題3: 文字列を繰り返し加工
Stream.iterate("A", s -> s.length() < 5, s -> s + "A")
.forEach(System.out::println);
// A, AA, AAA, AAAA
Java- ポイント: 文字列でも利用可能。終了条件で長さを制御。
テンプレート集
- 無限ストリーム → limit
Stream.iterate(seed, f).limit(n).forEach(...);
Java- 終了条件付き(Java 9+)
Stream.iterate(seed, cond, f).forEach(...);
Java- フィボナッチ数列
Stream.iterate(new int[]{0,1}, a -> new int[]{a[1], a[0]+a[1]})
.limit(n)
.map(a -> a[0])
.toList();
Java- 偶数列(終了条件付き)
Stream.iterate(2, x -> x <= max, x -> x+2).toList();
Java落とし穴と回避策
- Java 8 の iterate は無限: 必ず
limitを付けないと延々と生成してしまう。 - 終了条件の誤り: Java 9 の iterate では
hasNextPredicateが false になると終了。条件を正しく書く。 - 複雑な状態管理: 2つ以上の値を扱う場合は配列や小さなクラスで保持する。
- パフォーマンス: 大量生成はメモリに溜め込まず、逐次処理(forEach)で消費する。
まとめ
- Java 8:
Stream.iterate(seed, f)→ 無限ストリーム、limit必須。 - Java 9:
Stream.iterate(seed, cond, f)→ 終了条件付きで有限ストリームを直接生成可能。 - 用途: 数列生成、状態遷移、文字列加工など「次の値を逐次生成」する場面に便利。
👉 練習課題: 「Stream.iterate を使って 1〜50 の平方数を生成」してみると、Java 8 と Java 9 の違いが直感で理解できます。
