2017-05-02 6 views
5

流暢なAPIをOptionalにして、Consumerを2つ適用します。オプションの表示方法

私はこのような何かを夢見ています:

Optional.ofNullable(key) 
    .map(Person::get) 
    .ifPresent(this::printName) 
    .ifPresent(this::printAddress); // not compiling, because ifPresent is void 

は、どのように私は、一時変数に格納することなく、OptionalにいくつかのConsumer Sを適用していますか?

あなたはこの構文を使用することができます

答えて

4

ofNullable(key) 
    .map(Person::get) 
    .map(x -> {printName(x);return x;}) 
    .map(x -> {printAddress(x);return x;}); 
+3

これは動作しますが、私は副作用のためmap'が良いスタイルである '使用しないと思います:combineがある

Optional.ofNullable(key) .map(Person::get) .ifPresent(combine(this::printAddress, this::printWish)); 

。個人的には、 'ifPresent(x - > {doA(x); doB(x);})' –

+2

@RobinTopperと一緒に行くのがよいでしょう。 1つを見つけることに失敗し、彼らはそれを理解した後、次の検索者が実際に答えを見つけることを確認したい。 – Esko

+0

これは、Optionalが実際には遅延評価されたモナド(_yes、Java_の_yes)で、内部パイプラインが処理される最終的な値を要求した後でしかないということです - 最初に値がなければ、最終的な値を得るためのどのメソッドが呼び出されたかによって異なります。 – Esko

6

、これは非常に要素を思えないかもしれないが、私はちょうど1 lambdaに両方の効果を組み合わせてifPresentにそれを渡したい:また

ofNullable(key) 
    .map(Person::get) 
    .ifPresent(x -> {printName(x); printAddress(x);}); 

andThenを使用して複数のコンシューマーを連結することもできますが、これはメソッド参照をConsumerにキャストする必要がありますが、あまりエレガントではありません。たぶん

ofNullable(key) 
    .map(Person::get) 
    .ifPresent(((Consumer) this::printName).andThen(this::printAddress)); 
+0

実際に起こっていることがわかるように(* 2つのアクション、別のアクションが実行される)、より明白になります。 – slartidan

1

このような何か:

public <T> Consumer<T> combine(Consumer<T>... cs) { 
    return x -> Stream.of(cs).peek(c -> c.accept(x)).close(); 
} 
+0

これは '((Consumer)this :: printName).andThen(this :: printAddress)'にかなり似ていますが、私はそれをvarargsの面が好きです。 – slartidan

+1

また、消費者をいくつかの外部ソースから取得することもできますし、 'andThen'を使用する場合は、コンシューマをアンラップして' andThen'チェーンを手動で構築する必要があります。 –

関連する問題