Java 8ストリームはRxJavaオブザーバブルに似ていますか?
Java 8ストリーム定義:
新しい
Java.util.stream
パッケージのクラスは、要素のストリームで機能スタイルの操作をサポートするストリームAPIを提供します。
TL; DR:すべてのシーケンス/ストリーム処理ライブラリは、パイプライン構築用の非常に類似したAPIを提供しています。違いは、マルチスレッドとパイプラインの構成を処理するためのAPIにあります。
RxJavaはStreamとはまったく異なります。すべてのJDKの中で、rx.Observableに最も近いのはおそらく Java.util.stream.Collector ストリーム+ CompletableFutureコンボ(追加のモナドレイヤーを処理するコストがかかります。つまり、Stream<CompletableFuture<T>>
とCompletableFuture<Stream<T>>
の間の変換を処理する必要があります)。
ObservableとStreamには大きな違いがあります。
Stream#parallel()
はシーケンスをパーティションに分割しますが、Observable#subscribeOn()
とObservable#observeOn()
は分割しません。 ObservableでStream#parallel()
の動作をエミュレートするのはトリッキーです。かつて.parallel()
メソッドがありましたが、このメソッドは非常に混乱を引き起こし、.parallel()
サポートがgithubの別のリポジトリRxJavaParallelに移動しました。詳細は 別の回答 にあります。Stream#parallel()
では、オプションのスケジューラを受け入れるほとんどのRxJavaメソッドとは異なり、使用するスレッドプールを指定できません。 JVMのallストリームインスタンスは同じfork-joinプールを使用するため、.parallel()
を追加すると、プログラムの別のモジュールの動作に誤って影響する可能性がありますObservable#interval()
、Observable#window()
などの時間関連の操作がありません。これは主に、ストリームがプルベースであるためですtakeWhile()
、takeUntil()
); Stream#anyMatch()
を使用する回避策は制限されています。端末操作であるため、ストリームごとに複数回使用することはできません。Observable#using()
)を提供します。 IOストリームまたはミューテックスでラップし、ユーザーがリソースを解放することを忘れないようにしてください-サブスクリプションの終了時に自動的に破棄されます。ストリームにはonClose(Runnable)
メソッドがありますが、手動またはtry-with-resources経由で呼び出す必要があります。例Files#lines()mustをtry-with-resourcesブロックで囲む必要があることに注意してください。まとめ:RxJavaはStreamsとは大きく異なります。実際のRxJavaの代替は、 ReactiveStreams の他の実装です。 g。 Akkaの関連部分。
更新。 Stream#parallel
にデフォルト以外のfork-joinプールを使用するトリックがあります。 Java 8並列ストリームのカスタムスレッドプール を参照してください。
更新。上記のすべては、RxJava 1.xの経験に基づいています。 RxJava 2.xはここにあります であるため、この回答は古くなっている可能性があります。
Java 8 StreamとRxJavaはかなり似ています。似たような演算子(フィルター、マップ、flatMap ...)がありますが、同じ使用法では構築されていません。
RxJavaを使用して非同期タスクを実行できます。
Java 8ストリームを使用すると、コレクションのアイテムを走査します。
RxJava(コレクションのトラバースアイテム)でほぼ同じことを実行できますが、RxJavaは同時タスクに焦点を当てているため、...、同期、ラッチを使用するため、RxJavaを使用する同じタスクは、 Java 8ストリーム。
RxJavaはCompletableFuture
と比較できますが、それだけで複数の値を計算できます。
技術的および概念的な違いがいくつかあります。たとえば、Java 8ストリームは単一使用、プルベース、同期の値シーケンスです。値。 RxJavaはJava 6+を対象としており、Androidでも動作します。
Java 8 Streamsはプルベースです。各アイテムを消費するJava 8ストリームを反復処理します。そして、それは無限のストリームかもしれません。
RXJava Observable
はデフォルトでプッシュベースです。 Observableをサブスクライブすると、次のアイテムが到着したとき(onNext
)、ストリームが完了したとき(onCompleted
)、またはエラーが発生したとき(onError
)に通知されます。 Observable
を使用するとonNext
、onCompleted
、onError
イベントを受け取るため、異なるObservable
sを新しいものに結合するなどの強力な機能を実行できます(Zip
、merge
、concat
)。他にできることは、キャッシング、スロットリングなどです。そして、異なる言語(RxJava、C#のRX、RxJS、...)でほぼ同じAPIを使用します。
デフォルトでは、RxJavaはシングルスレッドです。スケジューラの使用を開始しない限り、すべてが同じスレッドで発生します。
既存の答えは包括的で正しいものですが、初心者向けの明確な例が不足しています。 「プッシュ/プルベース」や「再観察可能」などの用語の背景に具体的な説明を入れてください。 注:Observable
(これは天国のためのストリームです)という用語が嫌いなので、単にJ8対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
canreactが新しい各桁に反応し、リアルタイムでフィルターを適用します
even = -2-4-----6---------8----10------------12
入力および出力リストを保存する必要はありません。出力リストをwantしたい場合は、ストリーミングも問題ありません。実際、 すべてがストリームです。
evens_stored = even.collect()
これが、「ステートレス」や「機能」などの用語がRXにより関連している理由です。
RxJavaは reactive streams Initiative とも密接に関連しており、それをリアクティブストリームAPIの単純な実装と見なします(例: Akka streams implementation と比較)。主な違いは、リアクティブストリームがバックプレッシャーを処理できるように設計されていることですが、リアクティブストリームのページを見ると、アイデアが得られます。彼らは目標を非常によく説明しており、ストリームは reactive manifesto とも密接に関連しています。
Java 8ストリームは、ほとんど無制限のコレクションの実装であり、 Scala Stream または Clojure lazy seq と非常に似ています。
Java 8 Streamsは、マルチコアアーキテクチャを活用しながら、本当に大きなコレクションを効率的に処理できるようにします。対照的に、RxJavaはデフォルトでシングルスレッドです(スケジューラなし)。したがって、RxJavaは、そのロジックを自分でコーディングしない限り、マルチコアマシンを利用しません。