Optionalから値を取り出すにはorElseGet()を使う

公開日: : 最終更新日:2015/10/19 プログラム

Optional が値を持っていない場合のみ ◯◯ を実行する」を実装するときは Optional#orElseGet() を使う、という教訓のメモ。

Optional#orElseGet() とすべきところを Optional#orElse() で実装していたので、意図せぬバグを発生させるところだった。
簡単な例を使って Optional#orElseGet()Optional#orElse() の動きの違いを確認しておく。

icatch-2015-002

目次

1. Optional#orElseGet() を使った場合

簡単な例として、Optional#of("hoge") でインスタンスを生成し、orElseGet() を実行してみる。

Optional.of("hoge").orElseGet(() -> {
    log.info("-> Supplier_hoge"); // このログは出力されない
    return "fuga";
});

生成した Optional は “hoge” を持っているため orElseGet() は実行されない。
ラムダ式内に定義したログは出力されないことからそれが分かる。

では、Optional#empty() としてみる。

Optional.empty().orElseGet(() -> {
    log.info("-> Supplier_empty"); // このログは出力される
    return "fuga";
});

こちらは値を持っていないため orElseGet() が実行される。
ラムダ式内に定義したログが出力されることからもそれが確認できる。

2. Optional#orElse() を使った場合

上記と同様に Optional#of("hoge") でインスタンスを生成し、orElse() を実行してみる。

Optional.of("hoge").orElse(getDefault());

private static String getDefault() {
    log.info("-> getDefault"); // このログは出力される
    return "fuga";
}

生成した Optional は “hoge” を持っているにも関わらず orElse() が実行される。
getDefault() 内に定義したログが出力されることからそれが確認できる。

Opitonal が値を持っている場合 orElse() は実行してほしくないケースがほとんどだと思われるので、orElse() を使う場合は処理内容に気をつけたほうが良さそうだ。
特に、副作用が発生する処理を書いてしまうと、どこでそれが発生したのか見失うことになりかねない。個人的に要注意。

3. まとめ

  • Optional が値を持っていない場合のみ ◯◯ を実行する」を実装するときは Optional#orElseGet() を使う
    • 思い切って Optional#orElse() の使用はやめてみる
  • ラムダ式を使えば、必要になったタイミングで初めて計算されるので処理効率が上がる
    • もっと積極的にラムダ式を使ってみる

4. 更新履歴

  • 2015/10/10: 初版作成
  • 2015/10/19: 内容を編集

Googleアドセンス用(PC)

  • このエントリーをはてなブックマークに追加
  • follow us in feedly

関連記事

icatch-2015-006-1

バリデーションチェックにJava8のOptionalを使ってスマートに書く(自分比)

Web アプリのバリデーションチェックにアノテーションを使うことが増えた。だが、アノテーションで実装

記事を読む

icatch-back-scratcher_3553512020_mini-thumbnail

Sublime Text3 で JavaScript を書くために設定したプラグインとキーバインド

プロフィール にもあるように、ボクは Java をメインとしたプログラマです。 IDE には Ecl

記事を読む

icatch-markdown_6281167385_mini-thumbnail

Sublime Text3 で Markdown のシンタックスハイライトを有効にする手順

IT 関連の職場であれば、部署やチーム単位に Redmine とか Backlog を使って TOD

記事を読む

icatch-medium_4301351732-resized

mp3splt を実行して “undefined symbol: mp3splt_u_check_if_directory” と出力されたときの対処法

mp3 ファイルを分割してくれる mp3splt というライブラリがあります。 mp3 ファイルを

記事を読む

icatch_8626992930-resized

シェルスクリプトでcdしたいパスにスペースが入っている場合の対処法

cd したいパスにスペースが入っていると、パスの先頭からスペースまでを「移動したいパス」と解釈されて

記事を読む

icatch_3304032405-resized

CentOS に yum-plugin-priorities プラグインをインストールする

yum を使ってあるパッケージをインストールしようと調べていたところ、yum-plugin-prio

記事を読む

icatch-2015-003-1

Vagrantで起動したCentOS上のMySQLにホストOSからログインする設定

マシンを新しくしたこともあり、検証と称してソフトウェアをやみくもにインストールすることに抵抗が出てき

記事を読む

icatch-vacuum_9060011568_mini-thumbnail

GitHub にアップされているブランチをローカルに取り込む

GitHub に限らず、会社や自分で Git のサーバを使った場合にも当てはまりますが、毎回同じこと

記事を読む

icatch-pray_c916c87577_mini-thumbnail

Eclipse がエラーメッセージを出力して起動しなくなった場合の対処法

Eclipse の exe ファイルをクリックすると(または、実行すると)、 Eclipse のスプ

記事を読む

icatch_4365495446-resized

CentOS6.5にGitをソースコードからインストールする

CentOS 6.5 の64ビット版を "Minimal" でインストールした環境で、git sta

記事を読む

Googleアドセンス用(PC)

Message

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です


− 一 = 6

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Googleアドセンス用(PC)

icatch-jersey_multi_pathparams
Jerseyの@PathParamはスラッシュの間に複数指定できる

http://hoge-api/user/{id}.{format}

icatch-vagrant_box_customize
VagrantのBoxファイルをカスタマイズして独自のBoxファイルを作成する

配布されている Vagrant の Box ファイルを使って検証環境を

icatch-2015-006-1
バリデーションチェックにJava8のOptionalを使ってスマートに書く(自分比)

Web アプリのバリデーションチェックにアノテーションを使うことが増え

icatch-2015-005-1
ユニットテストの偏りを防ぐ命名規則の付け方

ユニットテスト名に以下の命名規則を付けるようにして二ヶ月ぐらい経った。

icatch-2015-004-1
Vagrantで起動したCentOS上のOctopressをホストOSから確認する設定

タイトルの通りだが、Vagrant を使って起動した CentOS に

→もっと見る

PAGE TOP ↑