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
Javamax(最大値)
List<Integer> nums = List.of(5, 2, 9, 1);
Optional<Integer> max = nums.stream().max(Integer::compare);
System.out.println(max.orElse(-1)); // 9
Javareduce(合計)
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 の便利さが体感できます。
