web-dev-qa-db-ja.com

Optional.ifPresent()の適切な使用法

Java 8.のOptional AP​​IのifPresent()メソッドを理解しようとしています。

私は簡単なロジックを持っています:

Optional<User> user=...
user.ifPresent(doSomethingWithUser(user.get()));

ただし、これによりコンパイルエラーが発生します。

ifPresent(Java.util.functionError:(186, 74) Java: 'void' type not allowed here)

もちろん、私はこのようなことをすることができます:

if(user.isPresent())
{
  doSomethingWithUser(user.get());
}

しかし、これは混乱したnullチェックとまったく同じです。

コードをこれに変更すると:

 user.ifPresent(new Consumer<User>() {
            @Override public void accept(User user) {
                doSomethingWithUser(user.get());
            }
        });

コードが汚れてきており、古いnullチェックに戻ることを考えさせられます。

何か案は?

70
rayman

Optional<User>.ifPresent()は、Consumer<? super User>を引数として取ります。型がvoidである式を渡します。そのためコンパイルできません。

Consumerは、ラムダ式として実装されることを目的としています。

Optional<User> user = ...
user.ifPresent(theUser -> doSomethingWithUser(theUser));

または、メソッドリファレンスを使用してさらに簡単に:

Optional<User> user = ...
user.ifPresent(this::doSomethingWithUser);

これは基本的に同じです

Optional<User> user = ...
user.ifPresent(new Consumer<User>() {
    @Override
    public void accept(User theUser) {
        doSomethingWithUser(theUser);
    }
});

doSomethingWithUser()メソッド呼び出しは、ユーザーが存在する場合にのみ実行されるという考え方です。コードはメソッド呼び出しを直接実行し、そのvoid結果をifPresent()に渡そうとします。

112
JB Nizet

@JBNizetの答えに加えて、ifPresentの一般的な使用例は、.isPresent().get()を組み合わせることです。

古い方法:

Optional opt = getIntOptional();
if(opt.isPresent()) {
    Integer value = opt.get();
    // do something with value
}

新しい方法:

Optional opt = getIntOptional();
opt.ifPresent(value -> {
    // do something with value
})

私にとって、これはより直感的です。

11
cst1992

FlatMapを使用します。値が存在する場合、flatMapはその値のみを含むシーケンシャルStreamを返し、そうでない場合は空のStreamを返します。したがって、ifPresent()を使用する必要はありません。例:

list.stream().map(data -> data.getSomeValue).map(this::getOptinalValue).flatMap(Optional::stream).collect(Collectors.toList());
6
Taras Melnyk

次のようなメソッド参照を使用できます。

user.ifPresent(ClassNameWhereMethodIs::doSomethingWithUser);

メソッドifPresent() get Consumerオブジェクトをパラメーターとして、および( JavaDoc )から:「値が存在する場合、その値で指定されたコンシューマーを呼び出します。」値は変数userです。

または、このメソッドdoSomethingWithUserUserクラスにあり、staticでない場合、次のようなメソッド参照を使用できます。

user.ifPresent(this::doSomethingWithUser);
4

単純にできるのに、なぜ複雑なコードを書くのですか?

実際、Optionalクラスを絶対に使用する場合、最も単純なコードは既に記述したものです...

if (user.isPresent())
{
    doSomethingWithUser(user.get());
}

このコードには、次の利点があります。

  1. 読みやすい
  2. デバッグが簡単(ブレークポイント)
  3. トリッキーではない

OracleがJava 8にOptionalクラスを追加したからといって、このクラスをすべての状況で使用しなければならないわけではありません。

4
schlebe