Java 8ストリームはRxJavaオブザーバブルに似ていますか?
Java 8ストリーム定義:
新しい
java.util.stream
パッケージのクラスは、要素のストリームに対する関数形式の操作をサポートするためのストリームAPIを提供します。
Java 8ストリームはRxJavaオブザーバブルに似ていますか?
Java 8ストリーム定義:
新しい
java.util.stream
パッケージのクラスは、要素のストリームに対する関数形式の操作をサポートするためのストリームAPIを提供します。
回答:
TL; DR:すべてのシーケンス/ストリーム処理ライブラリは、パイプライン構築用の非常に類似したAPIを提供しています。違いは、マルチスレッド処理とパイプラインの構成を処理するためのAPIです。
RxJavaはStreamとはかなり異なります。すべてのJDKの中で、rx.Observableに最も近いのは、おそらくjava.util.stream.Collector Stream + CompletableFutureコンボです(これは、追加のモナドレイヤーを処理するコスト、つまりとの間の変換を処理する必要がStream<CompletableFuture<T>>
ありますCompletableFuture<Stream<T>>
)。
ObservableとStreamの間には大きな違いがあります。
Stream#parallel()
パーティションにシーケンスを分割し、Observable#subscribeOn()
そしてObservable#observeOn()
ません。Stream#parallel()
Observableで動作をエミュレートするのはトリッキーです。以前は.parallel()
メソッドがありましたが、このメソッドは混乱を引き起こし、.parallel()
サポートがgithubのRxJavaParallelの別のリポジトリに移動しました。詳細は別の回答にあります。Stream#parallel()
オプションのスケジューラを受け入れるほとんどのRxJavaメソッドとは異なり、では使用するスレッドプールを指定できません。以来、すべての JVMにおけるストリーム・インスタンスは追加して、同じプールをフォークは、結合を使用.parallel()
誤ってプログラムの別のモジュールで動作に影響を与えることができますObservable#interval()
、Observable#window()
と多くの他。これは主に、ストリームがプルベースであり、上流が次の要素を下流に放出するタイミングを制御できないためですtakeWhile()
、takeUntil()
)。使用する回避策Stream#anyMatch()
は限られています。これは端末操作であるため、1つのストリームで複数回使用することはできませんObservable#using()
); IOストリームまたはミューテックスをラップして、ユーザーがリソースを解放するのを忘れないようにしてください-サブスクリプションの終了時に自動的に破棄されます。ストリームにはonClose(Runnable)
メソッドがありますが、手動でまたはtry-with-resourcesを介して呼び出す必要があります。例:Files#lines()はtry-with-resourcesブロックで囲む必要があることに注意してください。まとめ:RxJavaはStreamsと大きく異なります。実際のRxJavaの代替は、ReactiveStreamsの他の実装です(例:Akkaの関連部分)。
アップデート。にデフォルト以外のfork-joinプールを使用するトリックがあります。Java8 並列ストリームのカスタムスレッドプールをStream#parallel
参照してください
アップデート。上記のすべては、RxJava 1.xでの経験に基づいています。今すぐことRxJavaの2.xはここにある、この答えは時代遅れのかもしれません。
Stream.generate()
独自のSupplier<U>
実装を呼び出して渡すだけで、ストリーム内の次の項目を提供する1つの単純なメソッドになります。他にもたくさんの方法があります。Stream
以前の値に依存するシーケンスを簡単に構築するために、interate()
メソッドを使用できます。すべてCollection
にstream()
メソッドがあり、可変引数または配列からをStream.of()
構築しStream
ます。最後に、 StreamSupport
スプリッターを使用したより高度なストリーム作成またはストリームプリミティブタイプをサポートしています。
Java 8 StreamとRxJavaはかなり似ています。それらは似た演算子(filter、map、flatMap ...)を持っていますが、同じ使用法のために構築されていません。
RxJavaを使用して非同期タスクを実行できます。
Java 8ストリームでは、コレクションのアイテムをトラバースします。
RxJava(コレクションのトラバースアイテム)でもほぼ同じことができますが、RxJavaは並行タスクに重点を置いているため、同期、ラッチなどを使用します。したがって、RxJavaを使用する同じタスクは、 Java 8ストリーム。
RxJavaはと比較CompletableFuture
できますが、1つ以上の値を計算できます。
parallelStream
/シンプルトラバーサルの同様の同期をサポートしてマップする/フィルタリングなど。
いくつかの技術的および概念的な違いがあります。たとえば、Java 8ストリームは値の単一使用のプルベースの同期シーケンスですが、RxJava Observableは再観測可能で、適応的にプッシュプルベースの非同期の値のシーケンスである可能性があります。RxJavaはJava 6以降を対象としており、Androidでも動作します。
Java 8ストリームはプルベースです。各アイテムを消費するJava 8ストリームを反復処理します。そして、それは無限のストリームになる可能性があります。
RXJava Observable
はデフォルトでプッシュベースです。Observableをサブスクライブすると、次のアイテムが到着したonNext
とき()、ストリームが完了したonCompleted
とき()、またはエラーが発生したとき()に通知されますonError
。であるのでObservable
あなたが受け取るonNext
、onCompleted
、onError
イベントは、あなたが別の組み合わせのようないくつかの強力な機能を行うことができますObservable
新しいものにSを(zip
、merge
、concat
)。他にできることは、キャッシング、スロットルなどです...そして、それは多かれ少なかれ同じ言語を異なる言語で使用しています(RxJava、C#のRX、RxJSなど)。
デフォルトでは、RxJavaはシングルスレッドです。スケジューラの使用を開始しない限り、すべてが同じスレッドで発生します。
既存の答えは包括的で正しいですが、初心者のための明確な例は欠けています。「プッシュ/プルベース」や「再観測可能」などの用語を具体的に説明します。 注:私はこの用語Observable
(これは天国のためのストリームです)が嫌いなので、単にJ8 vs RXストリームを指します。
整数のリストを考えてみましょう。
digits = [1,2,3,4,5]
J8 Streamは、コレクションを変更するためのユーティリティです。たとえば、数字でも抽出できます。
evens = digits.stream().filter(x -> x%2).collect(Collectors.toList())
これは基本的にPythonのmap、filter、reduceであり、Javaに非常に便利な(そして長い間遅れている)追加です。しかし、事前に数字が収集されていなかった場合、つまり、アプリの実行中に数字がストリーミングされていた場合は、イベントをリアルタイムでフィルタリングできますか。
別のスレッドプロセスが、アプリの実行中にランダムな時間に整数を出力していると想像してください(---
時間を表します)
digits = 12345---6------7--8--9-10--------11--12
RXでは、even
することができます反応する各新しい桁に、リアルタイムでフィルタを適用
even = -2-4-----6---------8----10------------12
入力リストと出力リストを保存する必要はありません。出力リストが必要な場合は、ストリーミングも可能です。実際、すべてがストリームです。
evens_stored = even.collect()
これが、「ステートレス」や「機能的」などの用語がRXに関連している理由です。
RxJavaは、リアクティブストリームイニシアチブとも密接に関連しており、それ自体をリアクティブストリームAPIの単純な実装と見なしています(たとえば、Akkaストリームの実装と比較して)。主な違いは、リアクティブストリームはバックプレッシャを処理できるように設計されていることですが、リアクティブストリームページを見ると、アイデアがわかります。彼らは彼らの目標をかなりよく説明しており、ストリームは反応的なマニフェストにも密接に関連しています。
Java 8ストリームは、ほぼ無制限のコレクションの実装であり、Scala StreamまたはClojure lazy seqに非常に似ています。
Java 8 Streamsは、マルチコアアーキテクチャを活用しながら、非常に大きなコレクションを効率的に処理できるようにします。対照的に、RxJavaはデフォルトで(スケジューラなしで)シングルスレッドです。そのため、自分でロジックをコーディングしない限り、RxJavaはマルチコアマシンを利用しません。