0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Java Gold】Stream API について

Posted at

はじめに

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

ストリームAPIとは?

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

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

使用例

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 など)
  • 最も一般的
Stream<String> names = Stream.of("Alice", "Bob");

IntStream

  • int専用のストリーム。ボクシングのコスト回避
  • 特有メソッド:sum(), average(), range()など
IntStream.range(1, 5).forEach(System.out::println); // 1~4

LongStream

  • longに特化。IDや時刻の処理に有効
LongStream.of(100L, 200L, 300L);

DoubleStream

  • doubleに特化。統計や平均などの計算に便利
DoubleStream.of(1.5, 2.5, 3.5).average();

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

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

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

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[]>) 型付き配列非対応

おわりに

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

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?