2016-08-29 2 views
1

私は3つの条件を確認する必要があります。命令型プログラミングでは、私はここですべての3つのmeetsCriteria()メソッドが呼び出されていることを、ここで複数のオブザーバブルを結合するときにRxJavaに熱心に戻る方法は?

Observable<Boolean> foo(A a, B b, C c){ 
    Observable.zip(
    a.meetsCriteria(), 
    b.meetsCriteria(), 
    c.meetsCriteria(), 
    (bool1, bool2, bool3)->{return bool1 | bool2 | bool3;} 
} 

問題を反応性にする上記に変換するために私の愚かな試みだ

boolean foo(A a, B b, C c){ 
    if(a.meetsCriteria()){ return true; } 
    if(b.meetsCriteria()){ return true; } 
    if(c.meetsCriteria()){ return true; } 
    return false; 
} 

書きます、したがって、この実装は熱心に戻りません。 。 A.meetsCriteria()がtrueを返した場合、BとCのmeetsCriteria()は実行しません。正しい反応変換は何でしょうか?

+0

ニースのパズル実際、別のに基づいて1を実行しないように – karlicoss

+0

:)おかげで、あなたがそれらを呼び出す必要があります連続的に。ですから、単純に '||'を使用するのではなく、オブザーバブルでそれらを組み合わせようとするのは明確ではありません。 – njzk2

答えて

0

あなたは別の演算子が必要です。

a.meetsCriteria().flatMap(
    resa -> resa ? Observable.just(true) : b.meetsCriteria().flatMap(
     resb -> resb ? Observable.just(true) : c.meetsCriteria() 
    ) 
) 

はしかし、これは基本的に最悪の場合(すべての3つの基準が偽である)内のコードのシリアルになるだろう。むしろObservable.zipよりも、あなたはflatMapsのシーケンスを使用することができます。

リアクティブプログラミングの恩恵を受けるには、すべてを一度に実行する必要があります。それらのいずれかによって放出される

  • filtertrueアウト値
  • がフォールバックですdefaultIfEmpty(false)演算子を使う(彼らは並列で実行されます)

    1. merge観測を:私は、次のアイデアを作ってみましたすべての観測値が最後にfalse
    2. と表示された場合は、first()を使用してください。その結果、結果として単一のブール値が得られます。

    あなたはそれを自分で試すことができます正確に観察btrueを発するように必要な時間は約5秒で走る私のマシン上で

    Observable<Boolean> a = Observable.just(false).delay(15, TimeUnit.SECONDS); 
    Observable<Boolean> b = Observable.just(true).delay(5, TimeUnit.SECONDS); 
    Observable<Boolean> c = Observable.just(false).delay(50, TimeUnit.DAYS); 
    
    final Observable<Boolean> res = Observable.merge(a, b, c) 
          .filter(item -> item == true) 
          .defaultIfEmpty(false) 
          .first(); 
    
    System.err.println(res.toBlocking().first()); 
    

    を。あなたはしかし、そうした場合:

    Observable<Boolean> b = Observable.just(false).delay(5, TimeUnit.SECONDS); 
    

    、あなたはまあ、それは明らかにcがマージオペレータのためにすべてのものを放出するかどうかを知る手立てません:)終了するのに観察cために50日を待つことを運命なので、このされていますちょっと必然です。もちろん

    あなたがしようとした場合、あなたはまだ、並列処理の恩恵を受ける:

    Observable<Boolean> a = Observable.just(false).delay(10, TimeUnit.SECONDS); 
    Observable<Boolean> b = Observable.just(false).delay(10, TimeUnit.SECONDS); 
    Observable<Boolean> c = Observable.just(false).delay(10, TimeUnit.SECONDS); 
    

    、総走行時間は、シリアルバージョンでは約10秒ではなく30秒になります。

    P.S.私はそれがもっと自然なように感じます。コードは自明であるホープ:

    final Observable<Boolean> res = Observable.combineLatest(
        a.startWith((Boolean)null), 
        b.startWith((Boolean)null), 
        c.startWith((Boolean)null), 
        (Boolean b1, Boolean b2, Boolean b3) -> { 
         // note that b1/b2/b3 might be null 
         // we interpret that as 'unfinished' computation 
         if (Boolean.TRUE.equals(b1) || Boolean.TRUE.equals(b2) || Boolean.TRUE.equals(b3)) { 
          // if any of source observables has finished and was true, the result is obviously true 
          return true;   } 
         if (Boolean.FALSE.equals(b1) && Boolean.FALSE.equals(b2) && Boolean.FALSE.equals(b3)) { 
          // if all of source observables have finished and are false, the result is false 
          return false; 
         } 
         return null; // otherwise we're in some kind of intermediate state 
        } 
    ) 
        .filter(item -> item != null) 
        .first(); 
    
  • 0

    うーん...これについてどのように:

    return Observable.concatMap(
          a.meetsCriteria(), 
          b.meetsCriteria(), 
          c.meetsCriteria()) 
         .filter(value -> value) 
         .takeFirst(); 
    
    関連する問題