【Java Gold】Stream API について

## はじめに
JavaのストリームAPIについて、試験対策として整理しました。

## ストリームAPIとは？

JavaのStream APIは、大量のデータに対して「何をしたいか」を宣言的に記述できる仕組みです。従来のforループに比べ、簡潔で可読性の高いコードが書けます。

```java
List<String> names = List.of("Alice", "Bob", "Charlie");

names.stream()
     .filter(name -> name.length() > 3)
     .map(String::toUpperCase)
     .forEach(System.out::println); // 出力: ALICE, CHARLIE

```

このように、**中間操作 → 終端操作**の流れで処理パイプラインを構成します。

## Stream APIの特長

| 特長 | 説明 |
| --- | --- |
| 宣言的 | 「どうやるか」より「何をするか」を記述し、可読性が高い |
| 連結可能 | `.filter().map().sorted()`のように処理をチェーンできる |
| 遅延評価 | 中間操作は終端操作が呼ばれるまで実行されない |
| 並列処理しやすい | `.parallelStream()`で簡単に並列化可能 |
| イミュータブル | 元のデータを変更せず、副作用の少ない処理が可能 |


## ストリーム処理の3ステップ

| ステップ | 説明 | 例 |
| --- | --- | --- |
| 1. ストリーム生成 | コレクションなどからstreamを生成する | `list.stream()` |
| 2. 中間操作 | 絞り込み・変換などの処理（Streamを返す） | `filter()`, `map()` |
| 3. 終端操作 | 最終的な結果を取得または処理（値を返す） | `forEach()`, `count()` |


## Streamとforループの違い

| 項目 | forループ | Stream API |
| --- | --- | --- |
| スタイル | 命令型（手続き的） | 宣言型（関数型） |
| 副作用 | 変数を多用しやすく副作用が生まれやすい | 副作用を極力排除 |
| 並列処理 | 自分で実装が必要 | `.parallelStream()`で簡単に実装可能 |
| 集計結果取得 | 明示的にリストやカウンタが必要 | `collect()`, `count()`などで簡単 |

## 注意点

- Streamは一度しか使えない（再利用不可）
- インデックス付きの処理は難しい
- `null`要素の扱いには注意（例外の原因に）

## 中間操作（intermediate operations）一覧

中間操作はストリームの変換・フィルタリングなどを行い、別のストリームを返します。

（主要なもののみ抜粋）

| メソッド | 説明 | 引数 | 戻り値 |
| --- | --- | --- | --- |
| `filter` | 条件に合致する要素のみ残す | `Predicate<T>` | `Stream<T>` |
| `map` | 要素を変換（型変更も可） | `Function<T, R>` | `Stream<R>` |
| `flatMap` | ネストされた要素を平坦化 | `Function<T, Stream<R>>` | `Stream<R>` |
| `distinct` | 重複要素の除去 | なし | `Stream<T>` |
| `sorted` | 昇順ソート | `Comparator<T>` (省略可) | `Stream<T>` |
| `limit` / `skip` | 指定数の要素を取得/スキップ | `long` | `Stream<T>` |
| `takeWhile` | 条件がtrueの間だけ要素を取得 | `Predicate<T>` | `Stream<T>` |
| `dropWhile` | 条件がtrueの間はスキップ | `Predicate<T>` | `Stream<T>` |
| `peek` | 各要素に副作用処理を追加（デバッグ） | `Consumer<T>` | `Stream<T>` |


## 終端操作（terminal operations）一覧

終端操作はストリームを処理し、最終的な結果を得る操作です。

| メソッド | 説明 | 引数 | 戻り値 |
| --- | --- | --- | --- |
| `forEach` | 各要素に処理を適用 | `Consumer<T>` | `void` |
| `collect` | Listなどへ収集 | `Collector` | `Collection` |
| `reduce` | 要素を1つに集約 | `BinaryOperator`など | `Optional/T` |
| `count` | 要素数をカウント | なし | `long` |
| `min` / `max` | 最小 / 最大値を取得 | `Comparator<T>` | `Optional<T>` |
| `findFirst` | 最初の要素を返す（順序あり） | なし | `Optional<T>` |
| `findAny` | 任意の要素を返す（並列向き） | なし | `Optional<T>` |
| `anyMatch` | 条件に合う要素が1つでもあればtrue | `Predicate<T>` | `boolean` |
| `allMatch` | 全要素が条件を満たすならtrue | `Predicate<T>` | `boolean` |
| `noneMatch` | 条件を満たす要素がなければtrue | `Predicate<T>` | `boolean` |


## 使用例

```java
List<String> names = List.of("Alice", "Bob", "Charlie", "David", "Bob");

List<String> result = names.stream()
    .filter(name -> name.length() > 3)
    .distinct()
    .map(String::toUpperCase)
    .sorted()
    .collect(Collectors.toList());

System.out.println(result); // [ALICE, CHARLIE, DAVID]

```

## 補足ポイント

- `reduce` は引数の数により戻り値が異なる：1つの場合は `Optional<T>`、2つの場合は `T`
- `takeWhile`, `dropWhile` はJava 9以降で追加された便利な短絡操作
- `forEachOrdered` は順序を保証（並列時に有効）
- `peek` は本番コードでは使用注意（副作用）
- `mapToInt`, `mapToLong`, `mapToDouble` などはプリミティブ向けのストリームに変換するための操作

---

## `BaseStream`とは？

`java.util.stream.BaseStream<T, S extends BaseStream<T, S>>` は、すべてのStreamインターフェースの基本的な動作（例：`iterator()`、`spliterator()`、`close()` など）を定義する **共通のインターフェース** です。


## `BaseStream`の主なサブインターフェース一覧

| インターフェース名 | 要素型 | 説明 |
| --- | --- | --- |
| `Stream<T>` | 任意のオブジェクト型 | 一般的なオブジェクトに使うストリーム |
| `IntStream` | `int` | プリミティブ型 `int` のストリーム（ボクシング回避） |
| `LongStream` | `long` | プリミティブ型 `long` のストリーム |
| `DoubleStream` | `double` | プリミティブ型 `double` のストリーム |

## 各ストリームの特徴と使用例

### `Stream<T>`（オブジェクトストリーム）

- 任意のオブジェクト型（例：`String`, `User` など）
- 最も一般的

```java
Stream<String> names = Stream.of("Alice", "Bob");

```

### `IntStream`

- `int`専用のストリーム。ボクシングのコスト回避
- 特有メソッド：`sum()`, `average()`, `range()`など

```java
IntStream.range(1, 5).forEach(System.out::println); // 1～4

```

### `LongStream`

- `long`に特化。IDや時刻の処理に有効

```java
LongStream.of(100L, 200L, 300L);

```

### `DoubleStream`

- `double`に特化。統計や平均などの計算に便利

```java
DoubleStream.of(1.5, 2.5, 3.5).average();

```


## プリミティブストリームの活用ポイント

| 目的 | 使用するストリーム |
| --- | --- |
| 一般的なオブジェクト処理 | `Stream<T>` |
| 数値・統計処理 | `IntStream`, `LongStream`, `DoubleStream` |
| ボクシング回避による性能最適化 | プリミティブストリーム |
| 合計・平均・統計情報取得 | プリミティブストリーム専用メソッド |


## 型変換：プリミティブ → オブジェクト

```java
IntStream.range(1, 4)
         .boxed()
         .collect(Collectors.toList()); // Stream<Integer>

```

## IntStreamの中間操作一覧

| メソッド | 内容 | 引数 | 戻り値 |
| --- | --- | --- | --- |
| `filter` | 条件に一致する要素を残す | `IntPredicate` | `IntStream` |
| `map` | int同士の変換 | `IntUnaryOperator` | `IntStream` |
| `mapToObj` | オブジェクトに変換 | `IntFunction<R>` | `Stream<R>` |
| `flatMap` | 複数のIntStreamに展開 | `IntFunction<IntStream>` | `IntStream` |
| `distinct`, `sorted`, `limit`, `skip`, `takeWhile`, `dropWhile`, `peek` | 共通操作 | 型ごとの関数型インターフェース | `IntStream` |
| `boxed`, `asLongStream`, `asDoubleStream` | 型変換用 | - | 他のStream |


## IntStream専用中間操作（Streamでは使えない）

| メソッド | 説明 |
| --- | --- |
| `mapToObj`, `mapToLong`, `mapToDouble` | 型変換用 |
| `flatMap` | `IntFunction<IntStream>` を使用 |
| `boxed` | `Integer` へボクシング |
| `asLongStream`, `asDoubleStream` | 型変換用 |


## Streamで使えてIntStreamで使えない中間操作

| メソッド | 説明 |
| --- | --- |
| `map(Function)`, `flatMap(Function)` | 汎用的な型変換と展開 |
| `sorted(Comparator)` | カスタムソート |
| `unordered`, `onClose` | 並列・終了時処理 |
| `peek(Consumer)` | 汎用Consumer型の副作用処理 |


## IntStreamの終端操作一覧

| メソッド | 説明 | 戻り値 |
| --- | --- | --- |
| `forEach`, `forEachOrdered` | 各要素に処理 | `void` |
| `toArray()` | `int[]` に変換 | `int[]` |
| `reduce`, `sum`, `min`, `max`, `average` | 集計 | `OptionalInt`, `int`, `OptionalDouble` など |
| `summaryStatistics` | 統計取得 | `IntSummaryStatistics` |
| `collect(Supplier, ObjIntConsumer, BiConsumer)` | 集計カスタマイズ | 任意型 `R` |
| `anyMatch`, `allMatch`, `noneMatch`, `findFirst`, `findAny` | 条件・検索 | `boolean`, `OptionalInt` |


## IntStream専用終端操作（Streamでは使えない）

- `sum()`
- `average()`
- `min()`, `max()`（→ `OptionalInt`）
- `summaryStatistics()`


## Streamで使えてIntStreamで使えない終端操作

| メソッド | 説明 |
| --- | --- |
| `collect(Collector)` | `Collectors.toList()` など簡易集約 |
| `reduce(BinaryOperator<T>)` | ジェネリクス対応の汎用集約 |
| `toArray(IntFunction<A[]>)` | 型付き配列変換 |
| `iterator()`, `spliterator()` | イテレータ・スプリッタ取得 |
| `close()`, `onClose()` | リソースクローズ処理 |


## DoubleStream / LongStream の特有メソッド

| メソッド | 戻り値 | 説明 |
| --- | --- | --- |
| `sum()`, `average()`, `min()`, `max()` | `double`, `OptionalDouble`, `OptionalLong` | 数値集計 |
| `summaryStatistics()` | 統計オブジェクト | 全体の統計情報まとめて取得 |
| `mapToX()`, `boxed()`, `asXStream()` | 他型への変換 |  |


## DoubleStream/LongStreamで使えないStream専用メソッド

| メソッド | 説明 |
| --- | --- |
| `collect(Collector)` | `Collectors.toList()` など非対応 |
| `map(Function)`, `flatMap(Function)` | オブジェクト用 |
| `sorted(Comparator)` | カスタムソート非対応 |
| `onClose()`, `unordered()` | ストリーム制御関連 |
| `toArray(IntFunction<A[]>)` | 型付き配列非対応 |


## おわりに
誤記や改善点があればコメントなどでご指摘ください。