Loading

ROUTE

ルートゼロの
アクティビティ

Java OptionalのorElseとorElseGetの違い

2

JavaのOptional.orElseとorElseGetの違いは、代替値を作る処理をいつ実行するかです。orElse(fallback())はOptionalに値があってもfallback()の呼び出し式を先に評価します。一方、orElseGet(() -> fallback())は値がないときだけSupplierを呼び出します。重い処理や副作用のある処理を代替値に使うなら、orElseGetを検討してください。

orElseとorElseGetの違いを最初に比較

観点 orElse(T other) orElseGet(Supplier)
引数 代替値そのもの 代替値を作る関数
値がある場合 Optional内の値を返す。引数式の評価はすでに済んでいる Optional内の値を返す。Supplierを呼ばない
値がない場合 評価済みのotherを返す Supplierを実行して結果を返す
向く用途 固定文字列や軽い定数 DB呼び出し、計算、ログ付きの代替値生成

違いの中心は「Optionalの中身を選ぶ順番」ではなく、「メソッドを呼ぶ前の引数評価」と「Supplierの遅延実行」です。

用語解説:Supplier<T>
値を引数なしで生成して返すためのJavaの関数型インターフェースです。orElseGetへ渡すと、Optionalが空の場合にget()経由で呼び出されます。


値があるのに代替処理が走る理由

Javaでは通常、メソッドを呼ぶ前に引数式を評価します。したがってorElse(makeFallback())と書くと、Optionalが空かどうかに関係なくmakeFallback()が先に実行されます。

import java.util.Optional;

public class OptionalSample {
    static String makeFallback() {
        System.out.println("代替値を生成");
        return "guest";
    }

    public static void main(String[] args) {
        Optional<String> name = Optional.of("Alice");

        String a = name.orElse(makeFallback());
        String b = name.orElseGet(() -> makeFallback());

        System.out.println("orElse: " + a);
        System.out.println("orElseGet: " + b);
    }
}

この例ではmakeFallback()はorElseの引数式で1回だけ実行されます。nameはAliceを持つため、orElseGetのSupplier側は呼び出されません。実行を確認する場合はコンソール出力を比較してください。


Optionalが空の場合は両方とも代替値を返す

Optional<String> empty = Optional.empty();

String first = empty.orElse("guest");
String second = empty.orElseGet(() -> "guest");

System.out.println(first);
System.out.println(second);

この場合はどちらもguestになります。Optionalが空の場合、orElseGetのSupplierは実行されます。処理結果だけを見ると同じですが、代替値を作るタイミングが異なります。


固定値ならorElseでよい

代替値に単なる文字列や既に作成済みの変数を渡すなら、orElseを選ぶ方が読みやすい場合があります。すべてのorElseをorElseGetに書き換えれば速くなるわけではありません。

Optional<String> nickname = Optional.empty();
String shown = nickname.orElse("未設定");

一方、ファイル読み込み・データベースアクセス・オブジェクト生成・計算などが代替値にある場合、値が存在していても不要な仕事が起きていないか確認しましょう。

代替値の生成が重いならorElseGetを使う

import java.util.Optional;

class ProfileExample {
    static String loadDefaultProfile() {
        // 実際には設定やDBなどから取得する処理を想定
        return "default-profile";
    }

    static String showProfile(Optional<String> profile) {
        return profile.orElseGet(ProfileExample::loadDefaultProfile);
    }
}

このコードではprofileに値があればloadDefaultProfile()を呼び出しません。メソッド参照は実行を遅らせるSupplierとして働きます。

ただしorElseGetの中で副作用のある操作をすると、Optionalが空のときにその副作用は実行されます。ログ記録、書き込み処理、外部リクエストなどは、代替処理として本当に適切かを先に確認してください。

よくある書き間違いと例外

  • orElseGet(makeFallback())のように値を直接渡すと、Supplier<T>を要求するため通常は型が合いません。
  • orElseGet(() -> makeFallback())はSupplierを渡す正しい形です。
  • Optionalの中身がnullになる想定ではなく、ofNullable(null)で空Optionalを作るのが一般的です。
  • 必須値がないなら代替値よりorElseThrow()が適切な場合もあります。
  • nullのSupplierを渡すとOptionalが空の場合にNullPointerExceptionになるため避けます。
Optional<String> value = Optional.ofNullable(null);
String selected = value.orElseGet(() -> "guest");

Optional<String> required = Optional.empty();
// required.orElseThrow(); // 必須値なしを例外にする例

Optionalの結果が必要なのか、単なるデフォルト値が必要なのか、空なら例外にすべきなのかを区別するとAPIを選びやすくなります。

orElseGetが速いと決めつけない

「必ずorElseGetのほうが高速」と断定することはできません。代替値の計算量や実行頻度、JVMの最適化、実際のボトルネックによって差は変わります。

シーン 判断
固定文字列を返す orElseが簡潔
代替値の生成にI/Oがある orElseGetで不要な処理を回避
副作用を避けたい どの条件で実行されるかを明示
値がなければ処理を中止する orElseThrowの用途も確認

コードレビューでは「代替値の式がいつ評価されるか」と「副作用が許容されるか」を主に確認し、性能差は必要に応じて測定します。

関連するJavaの記事

Optionalはnullを扱うときの設計判断にも関係します。NullPointerExceptionの発生経路を確認したい場合は、Spring Bootでのnull対策の記事が役立ちます。また関数型の書き方に慣れるにはStreamの記事が参考になります。

(JavaとSpring Bootのnull対策については『Spring Boot NullPointerException完全対策|3大原因と実装例まとめ』をご参照ください)

(Javaの関数型処理の基礎については『Javaのfor文をStreamに書き換えるには?Spring Bootでの実践例付きでわかる!』をご参照ください)

よくある疑問とまとめ

orElseGetには必ずラムダ式が必要?

ラムダ式だけでなく、Supplier<T>に一致するメソッド参照も渡せます。

orElseは値があっても代替値を返す?

いいえ。Optionalに値があればその値を返します。ただしorElseへ渡す引数の計算は呼び出し前に行われます。

orElseGetでも副作用が発生する?

Optionalが空ならSupplierが実行されるため、副作用のある処理を入れれば発生します。

Optional.orElseとorElseGetは、どちらも値がない場合の代替値を扱うAPIです。代替値の生成が簡単な定数ならorElse、重い処理や副作用を伴う生成ならorElseGetの遅延実行が役立ちます。

代替値をメソッドで生成している箇所を見つけ、Optionalに値があるときも実行されてよいか確認してみてください。

カジュアル面談はこちら

RANKINGranking-icon

すべてを開示している会社です

ポジティブな面もネガティブな面も、包み隠さず誠実にお答えします。
気になることがあれば、面談の際にすべてオープンにお話します。