web-dev-qa-db-ja.com

first()とtake(1)の違い

RxJavaの詳細を理解しようとしています。

直感的に私はfirst()take(1)が等しく、同じことを期待していました。ただし、ソースコードを掘り下げることにより、first()take(1).single()として定義されます。

ここでsingle()は何に適していますか? take(1)は、単一のアイテムを出力することをすでに保証していませんか?

30
Paul Woitaschek

違いは、take(1)は上流から0..1アイテムをリレーするのに対し、firstは最初の要素をリレーするか、上流が空の場合はエラー(NoSuchElementException)を発行することです。どちらもブロックしていません。

それは真ですfirst == take(1).single()ここで、take(1)は上流の項目の数を1に制限し、single()は上流が空でないことを確認します。

この例は「完了」のみを出力します

Observable.empty().take(1)
.subscribe(System.out::println, Throwable::printStackTrace, 
    () -> System.out.println("Done"));

この例では、「1」に続いて「完了」を出力します。

Observable.just(1).take(1)
.subscribe(System.out::println, Throwable::printStackTrace, 
    () -> System.out.println("Done"));

この例では、「1」に続いて「完了」も出力します。

Observable.just(1, 2, 3).take(1)
.subscribe(System.out::println, Throwable::printStackTrace, 
    () -> System.out.println("Done"));

この例はNoSuchElementExceptionで失敗します

Observable.empty().first()
.subscribe(System.out::println, Throwable::printStackTrace, 
    () -> System.out.println("Done"));

この例でも、「1」に続いて「Done」が出力されます。

Observable.just(1).first()
.subscribe(System.out::println, Throwable::printStackTrace, 
    () -> System.out.println("Done"));

この例でも、「1」に続いて「Done」が出力されます。

Observable.just(1, 2, 3).first()
.subscribe(System.out::println, Throwable::printStackTrace, 
    () -> System.out.println("Done"));

この例では、ソースに含まれる要素が少なすぎるため、NoSuchElementExceptionのスタックトレースを出力します。

Observable.empty().single()
.subscribe(System.out::println, Throwable::printStackTrace, 
    () -> System.out.println("Done"));

この例では、ソースに含まれる要素が多すぎるため、IllegalArgumentExceptionのスタックトレースを出力します。

Observable.just(1, 2, 3).single()
.subscribe(System.out::println, Throwable::printStackTrace, 
    () -> System.out.println("Done"));
35
akarnokd

実装の違いは、セマンティクスの違いによって引き起こされます。言語とその内部の仕組みについての知識がない場合は、これら2つの方法が何を意味するかを検討してください。

first()は、要素を1つだけ返すことを意味します。コレクションの最初の要素。

take(x)は、要素のコレクションを返すことを意味します。コレクションの最初のx要素。

異なるセマンティクスは異なる名前を要求します。また、戻り値が異なると、技術的な実装も異なります。

また、2つの実装がエラー状態をまったく異なる方法で処理する可能性もあります(ここでも、技術的な答えを得るために内部を調べる必要はありません)。最初の要素がないため、個人的にはfirst()が空のコレクションの例外をスローすることを期待します。ただし、最初のコレクションの要素がx未満の場合、take(x)xのサイズよりも小さいコレクションをエラーなしで返すと合理的に期待できます。 may空のコレクションが与えられると、エラーなしで空のコレクションが返されます。

さらに、技術的な問題として、take(x)のようなものは、実際に基になるコレクションをすぐに反復するのではなく、何かがその結果を反復するまで延期する可能性が高くなります。ただし、first()は、基礎となるコレクションの最初の要素を反復して実体化する必要があります。

5
David