Stream API(Java 8+)は、コレクションの関数型スタイルでの処理を可能にします — フィルタリング、変換、データの集約を操作のパイプラインを通じて行い、明示的なループ(どうするか)ではなく宣言的に(何をするか)表現されます。
なぜ重要なのか
java
// ❌ imperative — explicit loop, mutable accumulator
List<String> result = new ArrayList<>();
for (Person p : people) {
if (p.getAge() >= 18) {
result.add(p.getName().toUpperCase());
}
}
// ✅ stream — declarative pipeline, reads like a description of the transformation
List<String> result = people.stream()
.filter(p -> p.getAge() >= 18) // keep adults
.map(p -> p.getName().toUpperCase()) // extract + transform names
.collect(Collectors.toList()); // gather into a list
ストリームバージョンは、手動ループやアキュムレータなしで、操作のチェーンとして意図を明確に表現します。
パイプラインの構造
text
Source → Intermediate operations (lazy) → Terminal operation (triggers execution)
java
stream() // source
.filter(...) .map(...) // intermediate — lazy, return a new stream, chainable
.collect(...) // terminal — produces a result, RUNS the pipeline
中間操作(filter、map、sorted、distinct)は遅延です — パイプラインを構築しますが、ターミナル操作(collect、forEach、reduce、count)がトリガーされるまで実行されません。
一般的な操作
java
list.stream()
.filter(x -> x > 0) // keep matching
.map(x -> x * 2) // transform each
.sorted() // sort
.distinct() // remove duplicates
.limit(10) // take first 10
.collect(Collectors.toList());
// aggregations
int sum = nums.stream().mapToInt(Integer::intValue).sum();
long count = list.stream().filter(...).count();
Optional<Person> first = people.stream().filter(...).findFirst();
boolean any = list.stream().anyMatch(x -> x > 100);
// grouping (very powerful)
Map<String, List<Person>> byCity =
people.stream().collect(Collectors.groupingBy(Person::getCity));
reduce — 単一の値に折り畳む
java
int total = nums.stream().reduce(0, (a, b) -> a + b); // sum via reduction
並列ストリーム
java
list.parallelStream().filter(...).collect(...); // process across multiple cores
// ⚠️ use only for large data + independent/stateless operations; measure first
なぜ重要なのか
Stream APIはJavaがデータを処理する方法を変えました — 冗長でエラーが発生しやすいループを、フィルタリング、マッピング、ソート、グループ化、集約のための簡潔で読みやすい宣言型パイプラインに置き換えました。
モダンJavaのデータ操作で広く使用されており、コードの意図をより明確にし、ラムダとメソッド参照と統合して関数型スタイルを実現します。
遅延中間/即座ターミナルモデル、一般的な操作(filter/map/collect/reduce/groupingBy)、および並列ストリーム(その注意点を含む)のオプションを理解することは、イディオマティックなモダンJavaを書くために不可欠です。
ストリームは生産性の向上とインタビューの頻出トピックの両方であり、最新のJavaプラクティスに対する流暢さを反映しています。
