maxの返り値はOptional型
Streamのメソッドにmax
(以下、min
も同様)というものがある。一見、Streamの最大値をそのまま返すように見えるが、返り値の型は以下の例の通りOptionalである。
コード
List<Integer> integerList = Arrays.asList(1, 2, 3);
Optional<Integer> maxIntegerOpt = integerList
.stream()
.max(Integer::compareTo);
System.out.println("maxIntegerOpt = " + maxIntegerOpt);
実行結果
maxIntegerOpt = Optional[3]
ということは最大値が見つからない場合もあるということである。
色んな値のStreamで試してみた
「え、最大値が見つからないことってあるの?」と疑問に思ったので、色んな値のStreamで試してみた。
重複する値がある場合は見つかる
ははーん、きっと値が重複してたら最大値が一意に定まらないから最大値なしとなるんだな!
コード
List<Integer> integerList = Arrays.asList(1, 2, 3, 3);
Optional<Integer> maxIntegerOpt = integerList
.stream()
.max(Integer::compareTo);
System.out.println("maxIntegerOpt = " + maxIntegerOpt);
実行結果
maxIntegerOpt = Optional[3]
げぇー!重複してるのは一つの値としてまとめて判定している!地味にこれは新たな発見。
Streamが空の場合は見つからない
正解はこちら。
コード
List<Integer> integerList = Collections.emptyList();
Optional<Integer> maxIntegerOpt = integerList
.stream()
.max(Integer::compareTo);
System.out.println("maxIntegerOpt = " + maxIntegerOpt);
実行結果
maxIntegerOpt = Optional.empty
まあ要素が無ければ最大値も調べようがないですよね。てか公式に書いてました。マニュアル読めって話。
Streamが空になるシチュエーション
※コメントを受けて追記しました。
空Streamに対して最大値を取りに行くシチュエーションある?と思っていましたが、間にfilter
などを噛ます場合は途中でStreamが空になります。
例えば以下のような、100以下の値でfilter
をかけて最大値を取りに行く場合は途中でStreamが空になり、空Optionalが返ります。
コード
List<Integer> integerList = Arrays.asList(101, 104);
Optional<Integer> maxIntegerOpt = integerList
.stream()
.filter(integer -> integer <= 100)
.max(Integer::compareTo)
この場合、結果が空Optionalということはfilter
に該当する要素がなかったということなので、結果を利用する側でその場合の処理を書く必要があります(そのためのOptional)。
空Optionalを返すのってどうよ?
要するにmax
はStreamが空でもエラーとせず、空Optionalを返してくれます。
しかし直感的にその動作がわかるでしょうか?最大値を調べようがなく、自分はてっきり何か例外が返ってくるものだと思っていましたので、空Optionalが返ってくることに違和感を感じていました。
※ご指摘いただき、Optional
で返すことで、空Streamでも例外とならないことが明らかだと判断しました。