で、結局 Optional のインスタンスに対して ifNotPresent 的なことをやりたいときはどうしたらいいんですか？

# 前置き

表題の件について、要するに

```java
T t = getT();

if (t != null) {
    t.method();
} else {
    logger.warn("Not found.");
}
```

的なことを、`Optional<T>` のときどうすればいいのかがわからずにずっともやもやしてきた。
なので、ちょっと腰を据えて考えてみた。
先に断っておきますが、考えただけなので明確な結論はありません。すいません。

# 実践例！？

## ifPresent

```java
// 以下のコード例で、opt は Optional<T> のインスタンス。

opt.ifPresent(t -> t.method());
```

`ifPresent` を使うと、else 節がくっつけられないのでだめ。`ifPresent` はそもそもそういうものなんだろうとは思うが。

## isPresent

```java
if (opt.isPresent()) {
    T t = opt.get();
    t.method();
} else {
    logger.warn("Not found.");
}
```

言うまでもなく `Optional` がなかった頃から何も進歩していないのでだめ。`null` を生で扱っているのと大差ない。
なお、`Optional` についてぐぐれば、よくない例としてよく出てきて `ifPresent` を使えと言われる。しかし、else 節はどうするのかについては大抵言及されていない・・・。

## map/orElseGet

```java
opt.map(t -> {t.method(); return t;})
    .orElseGet(() -> {logger.warn("Not found."); return null;});
```

一応、流れるように書けている気がしないでもない。
しかし、`map` 本来の使い方じゃなさそうな気がひしひしするし、`return` に無理矢理感が漂う。

## Runnable を返す （あるいは、迷走の始まり）

```java
opt.<Runnable>map(t -> () -> t.method())
    .orElse(() -> logger.warn("Not found."))
    .run();
```

要するに else の時に行いたい「処理」をどう扱うかというのが問題なので、いっそのことその「処理」つまり function を丸ごと扱えばいいんじゃないの？という発想。
いやしかし、else の方はいいとして、else じゃないほうを else に合わせてしまっている本末転倒ぶりがちょっと・・・。
ここまで来ると何をやってるか、何をやりたいかが見た目ですぐにわからない。それはお世辞にも良いプログラミングとはいえない。

## utility method （迷走は続く）

```java
// 名前付けは適当ですすいません
public class OptionalUtils {
    public static <T> void ifPresentOrElse(Optional<T> opt, Function<T, Runnable> ifPresent, Runnable orElse){
        opt.map(ifPresent).orElse(orElse).run();
    }
}
```

```java
OptionalUtils.ifPresentOrElse(opt
    , t -> () -> t.method()
    , () -> logger.warn("Not found."));
```

わかりにくいなら、わかりやすいインターフェースでくるんでやればいいんじゃない？という発想。この spreadsheet の if 文のようなインターフェースがわかりやすいか、という話はさておいて。
いやしかし、こんなことをしても `Function<T, Runnable>` の部分の違和感が解消されていないのでなんの解決にもなっていないのであった・・・。

でも、これ処理が分離できているので、使い方によればテストしやすくなってるんじゃないかとふと思った。

## wrapping

```java
class OptionalEx<T> {

    private Optional<T> opt;
    
    private OptionalEx(Optional<T> opt) {
        if (opt == null) {
            opt = Optional.empty();
        } else {
            this.opt = opt;
        }
    }
    
    public static <T> OptionalEx<T> of(Optional<T> opt) {
        return new OptionalEx<>(opt);
    }
    
    public OptionalEx<T> ifPresent(Consumer<T> c){
        opt.ifPresent(c);
        return this;
    }
    
    public OptionalEx<T> ifNotPresent(Runnable r){
        if(!opt.isPresent()){
            r.run();
        }
        return this;
    }
}
```

```java
OptionalEx.of(opt)
    .ifPresent(t -> t.method())
    .ifNotPresent(() -> logger.warn("Not found."));
```

我に返って、べたにラッピングで実装。
やりたいことには近づいている気はするが・・・。たかだか else 節のためにここまでしないといけないのか！？
Optional をさらに包むとかちょっと気持ち悪い・・・。

# 結論のような何か

## 仮の結論

結局、どうしたらいいんですかね？
なんだかんだ言って、このケースは `isPresent` が無難なんですかね？　えー・・・。

## 真の？結論

なお、割と早いうちに、「そもそも `Optional` の使い方を逸脱してるから上手くいかないんじゃないか」と心の中でささやく声が聞こえたような気がします。

## 最終的な結論

コメントにも頂いていますが、JDK9 には `ifPresentOrElse` が追加されるようなので、JDK9 に期待しましょう。
~~リリースがいつの事になるやら分からんけどな。~~

(2017-09-24 追記)
無事 JDK9 がリリースされましたので、9 以降を使う（使える）場合は是非 `ifPresentOrElse` を使いましょう。　[sample code](https://gist.github.com/mdstoy/644be264dfc103ef3ba851fb8d7cac9a)

# 参考

http://stackoverflow.com/questions/23773024/functional-style-of-java-8s-optional-ifpresent-and-if-not-present
http://stackoverflow.com/questions/29235982/how-to-execute-logic-on-optional-if-not-present