Java 8以降で使える Stream API は、
「for文を書かずにデータを処理できる便利な仕組み」です。
ただし、配列・List・Mapではストリームの作り方が異なるため、
初心者の方が混乱しやすいポイントでもあります。
この記事では、
- 配列・List・Mapでのストリーム生成の違い
- なぜ
Stream.of()はプリミティブ配列で使えないのか
を、できるだけ噛み砕いて解説します。
1. そもそも Stream とは?
Stream とは簡単に言うと、
「データの流れを作って、順番に処理する仕組み」
です。
list.stream()
.filter(x -> x > 10)
.toList();
このように、
- データを流し始める(ストリーム生成)
- 条件で絞る・変換する
- 結果をまとめる
という流れで処理します。
2. データ構造ごとのストリーム生成方法
まず全体像を見てみましょう。
| データ構造 | ストリーム生成方法 |
|---|---|
| 配列 |
Arrays.stream() / Stream.of()
|
| List | list.stream() |
| Map |
keySet() / values() / entrySet()
|
ここから1つずつ見ていきます。
3. 配列のストリーム生成
3.1 オブジェクト配列の場合(Stringなど)
String[] names = {"Alice", "Bob", "Charlie"};
Arrays.stream(names)
.forEach(System.out::println);
または
Stream.of(names)
.forEach(System.out::println);
この2つは 同じように使えます。
4. 【重要】プリミティブ配列と Stream.of() の落とし穴
ここが stream.of() のポイントです。
4.1 プリミティブ配列とは?
Javaの基本型(プリミティブ型)には次のようなものがあります。
intlongdoubleboolean
これらの配列が プリミティブ配列 です。
int[] numbers = {1, 2, 3};
4.2 うまくいく例(Arrays.stream)
int[] numbers = {1, 2, 3};
Arrays.stream(numbers)
.forEach(System.out::println);
これは問題なく動きます。
出力結果は次のようになります。
1
2
3
なぜなら、
-
Arrays.stream(int[])は - IntStream(int専用Stream) を返す
ように作られているからです。
4.3 失敗する例(Stream.of)
int[] numbers = {1, 2, 3};
Stream.of(numbers)
.forEach(System.out::println);
一見正しそうですが、これは 期待した動きをしません。
出力結果は次のようになります。
[I@6d03e736
「1, 2, 3」ではありません。
5. なぜ Stream.of() はプリミティブ配列で使えないのか?
結論から言うと:
Stream.of() は「配列の中身」ではなく「配列そのもの」を1要素として扱うから
です。
5.1 イメージで理解する
オブジェクト配列の場合
String[] names = {"A", "B", "C"};
Stream.of(names);
Streamはこう解釈します。
"A" → "B" → "C"
プリミティブ配列の場合
int[] numbers = {1, 2, 3};
Stream.of(numbers);
Streamはこう解釈します。
int[](配列そのもの) ← これが1要素
つまり、
-
Stream<int[]>が作られる -
Stream<Integer>やIntStreamにはならない
ということです。
5.2 なぜそんな仕様なのか?
理由はJavaの型の仕組みにあります。
-
Stream.of(T... values)は オブジェクト専用 - プリミティブ型(intなど)はオブジェクトではない
- そのため 配列を分解できない
この制約を回避するために、Javaは次を用意しています。
IntStreamLongStreamDoubleStream
そしてそれを返すのが Arrays.stream() です。
6. List のストリーム生成(最も簡単)
List<String> list = List.of("A", "B", "C");
list.stream()
.forEach(System.out::println);
特徴
- 直感的
- 失敗しにくい
- 実務で最もよく使う
7. Map のストリーム生成
MapはそのままではStreamを作れません。
map.stream(); // コンパイルエラー
理由は、
Mapは「キー」と「値」のペア構造だから
です。
使い分け
map.keySet().stream(); // キーだけ
map.values().stream(); // 値だけ
map.entrySet().stream(); // キーと値のセット
8. まとめ(初心者向け整理)
| データ構造 | ポイント |
|---|---|
| 配列 |
Arrays.stream() が安全 |
| プリミティブ配列 |
Stream.of() は使えない |
| List |
list.stream() が基本 |
| Map | 流す対象を必ず選ぶ |
特に重要
- プリミティブ配列 × Stream.of() はNG
- 理由は「配列が1要素として扱われるから」