2017-07-18 5 views
1

Java 8では、Optionalが存在する場合にメソッドを強制的に返す方法はありますか? 私は答えがノーだと思います。しかし、次のコードでisPresent()get()を使用しないようにするには?Java 8のオプションが存在する場合はメソッドが返されます

public Bar myMethod(){ 
    if(condition){ 
     return getOptionalFoo() 
       .map(Foo::getBar) 
       .orElseGet(() -> getOtherBar()); 
    } 

    return getOtherBar(); 
} 

しかし、今、私たちは二度getOtherBarへの呼び出しを記述するので、それは良いアイデアのように見えるしていません:

public Bar myMethod(){ 
    if(condition){ 
     Optional<Foo> foo = getOptionalFoo(); 
     if(foo.isPresent()){ 
      return foo.get().getBar(); 
     } 
    } 

    return getOtherBar(); 
} 

一つの解決策は、書くことだろう。これを避ける方法はありますか?

編集:私はまた

public Bar myMethod(){ 
    //Or a ternary operator but there are hard to read when they make long lines 
    Optional<Foo> foo; 
    if(condition){ 
     foo = getOptionalFoo(); 
    } else { 
     foo = Optional.empty(); 
    } 

    return foo.map(Foo::getBar) 
     .orElseGet(() -> getOtherBar()); 
} 

考えるしかし、ここで問題は、我々はそれに役に立たない空Optionalとチェーンのメソッドを作成することです。条件が時間の99%に満たない場合は、元のコードよりも効率が悪くなります(特に、複数の場合はmap()filter())。

注:実際に私たちのコードでは、他の呼び出し(fooに依存する)の結果に依存するより多くの条件があります。

+0

これらの2つの方法の間にコンパイラとの違いはありません。アプリケーションでこれらの両方を使用することはできません –

+1

@rabbitguy私はあなたのステートメントを理解していません – Ricola

答えて

3

これはいかがですか?以下のコードの形態は可読以上であるが、それはあなたより遅い、conditionが満たされない場合ので、getOtherBar()Optionalに追加操作(map & orElseGet)を必要とします。重複の多くは、上記のように好きであるかどう

public Bar myMethod() { 
    Optional<Foo> source = condition ? getFoo() : Optional.empty(); 

    return source.map(Foo::getBar) 
       .orElseGet(this::getOtherBar); 
} 

しかし、その後は、たとえば、抽出方法を自分自身を解放することができます。

private Optional<Foo> foo(){ 
    return condition ? getFoo() : Optional.empty(); 
} 

public Bar myMethod() { 
    return foo().map(Foo::getBar).orElseGet(this::getOtherBar); 
} 

public Other otherMethod() { 
    return foo().map(Foo::getOther).orElseGet(this::getOther); 
} 
2

これはかなり簡単にあなたに得れば一緒に落ちますOptionalの考え方を使用し、3値演算子を使用して条件を処理します。

public Bar myMethod(){ 
    return (condition ? getOptionalFoo() : Optional.<Foo> empty()) 
     .map(f -> f.getBar()) 
     .orElseGet(() -> getOtherBar()) 
} 
3

conditionとは何ですか?それはインスタンスメソッドに配置されているため、インスタンスの状態に応じた条件でなければなりません。これはあなたのクラスのフィールドであることを前提と簡単にするために、あなたは

public Bar myMethod() { 
    return Optional.of(this) 
     .filter(obj -> obj.condition) 
     .flatMap(ClassContainingMyMethod::getFoo) 
     .map(Foo::getBar) 
     .orElseGet(this::getOtherBar); 
} 

を書くことができgetFoo()は高価ではありませんし、副作用を持たない場合、あなたはするつもりはない場合でも、常にそれを呼び出して受け入れることができますその結果をconditionに応じて使用してください。コードを簡略化します

public Bar myMethod() { 
    return getFoo() 
     .filter(foo -> condition) 
     .map(Foo::getBar) 
     .orElseGet(this::getOtherBar); 
} 

元のコードには意味の違いがあります。 getBarnullを返した場合、元のコードはnullを返しますが、Optional.mapの結果を返す関数を使用するコードはすべてgetOtherBar()に戻ります。

+0

私が提供した例は、私たちが遭遇したものの本当に単純な例です。実際の方法はそれより複雑で、実際には複数のif条件がありました。 条件がメソッドのパラメータのみに依存する場合、読者が 'Optional.of(this)).filter(obj-> conditionThatDoesNotDependOnTheInstance)'を読むのは混乱してしまうからです。 いくつかは、それに依存しない条件で'foo 'をフィルタリングするためのものです。 – Ricola

+0

@リコラ:あなたはあなたの例を単純化しすぎました。それがまさに私が「条件とは何か?」という質問をした理由です。それがパラメータの条件であれば、代わりに 'Optional.of(parameter).filter(predicateOfParameter)'を使うことができます。条件に複数のパラメータを組み合わせたり、さらに複雑なものがある場合は、条件コード全体を単一の 'boolean'返り値のメソッドにリファクタリングするか、可能でない場合は複雑な条件でよりうまく動作する' if'ステートメントを使います。ラムダ式は小さなコードのみを対象としています。 – Holger

+0

あなたの最後の文章は実際に私の質問に対する本当の答えだと思います。 "ラムダ式は小さなコードのみを対象としています。 私はそれを念頭に置いておきます、ありがとう。 – Ricola

関連する問題