Java 逆引き集 | Optional を返すストリーム処理パターン — null 安全

Java Java
スポンサーリンク

Optional を返すストリーム処理パターン — null 安全

Java の Stream API は「結果があるかどうか分からない」処理をするときに Optional を返すメソッドを備えています。これにより、null を返す代わりに「値がある/ない」を安全に表現できます。初心者がつまずきやすい「Optional の扱い方」を、例題とテンプレートで整理します。


Optional を返す代表的なメソッド

  • findFirst(): 最初の要素を返す。空なら Optional.empty()
  • findAny(): どれかひとつの要素を返す(並列ストリームで効率的)。
  • max(Comparator): 最大値を返す。空なら Optional.empty()
  • min(Comparator): 最小値を返す。空なら Optional.empty()
  • reduce(BinaryOperator): 集約結果を返す。空なら Optional.empty()
  • average(): プリミティブストリームの平均値。空なら OptionalDouble.empty()

基本コード例

findFirst(最初の要素)

List<String> words = List.of("apple","banana","cherry");

Optional<String> first = words.stream().findFirst();
System.out.println(first.orElse("NA")); // apple
Java

max(最大値)

List<Integer> nums = List.of(5, 2, 9, 1);

Optional<Integer> max = nums.stream().max(Integer::compare);
System.out.println(max.orElse(-1)); // 9
Java

reduce(合計)

List<Integer> nums = List.of();

Optional<Integer> sum = nums.stream().reduce((a,b) -> a+b);
System.out.println(sum.orElse(0)); // 空なら0
Java

例題で理解する

例題1: ログから最初の ERROR を探す

List<String> logs = List.of("INFO start","WARN retry","ERROR failed","ERROR timeout");

String firstError = logs.stream()
    .filter(l -> l.contains("ERROR"))
    .findFirst()
    .orElse("No error");

System.out.println(firstError); // ERROR failed
Java
  • ポイント: 空なら「No error」と安全に返せる。

例題2: 学生の最高点を取得

record Student(String name, int score) {}

List<Student> students = List.of(
    new Student("Tanaka",80),
    new Student("Sato",55),
    new Student("Ito",90)
);

Student top = students.stream()
    .max(Comparator.comparingInt(Student::score))
    .orElse(null);

System.out.println(top.name()); // Ito
Java
  • ポイント: Optional.orElse(null) で「見つからなければ null」を返すこともできる。

例題3: 平均値を安全に扱う

IntStream empty = IntStream.empty();

double avg = empty.average().orElse(Double.NaN);
System.out.println(avg); // NaN
Java
  • ポイント: 平均値が存在しない場合に NaN を返す。

テンプレート集

  • 最初の要素を安全に取得
Optional<T> opt = stream.findFirst();
T value = opt.orElse(defaultValue);
Java
  • 最大値/最小値
Optional<T> max = stream.max(Comparator.comparing(...));
Optional<T> min = stream.min(Comparator.comparing(...));
Java
  • reduce の結果
Optional<T> result = stream.reduce((a,b) -> combine(a,b));
Java
  • Optional の安全な利用
opt.ifPresent(v -> System.out.println(v)); // 値があるときだけ処理
Java
  • プリミティブストリームの平均
double avg = IntStream.of(...).average().orElse(0.0);
Java

落とし穴と回避策

  • Optional.get() の乱用: 値がないと NoSuchElementException。必ず orElse, orElseGet, ifPresent を使う。
  • null と Optional の混在: Optional を返すメソッドは null を返さない。null を返す設計は避ける。
  • 空ストリーム: findFirst/max/min/reduce は空なら Optional.empty。必ず安全に扱う。
  • OptionalDouble/Long/Int: プリミティブストリームは専用 Optional 型を返す。orElse でデフォルト値を指定する。

まとめ

  • Stream の「候補抽出」や「集約」は Optional を返すことが多い。
  • Optional を使うことで null 安全に「値がある/ない」を表現できる。
  • orElse, ifPresent, orElseGet を活用して安全に処理するのが基本。

👉 練習課題: 「社員リストから最初の退職予定者を findFirst で探し、見つからなければ ‘なし’ と表示する」コードを書いてみると、Optional の便利さが体感できます。

タイトルとURLをコピーしました