Java 8流是否类似于RxJava可观察到的?
Java 8流定义:
新
java.util.stream
包中的类提供了Stream API,以支持对元素流进行功能样式的操作。
Java 8流是否类似于RxJava可观察到的?
Java 8流定义:
新
java.util.stream
包中的类提供了Stream API,以支持对元素流进行功能样式的操作。
Answers:
TL; DR:所有序列/流处理库都为管道构建提供了非常相似的API。区别在于用于处理多线程和管道组成的API。
RxJava与Stream完全不同。在所有JDK中,最接近rx.Observable的可能是java.util.stream.Collector Stream + CompletableFuture组合(这需要处理额外的monad层,即必须处理Stream<CompletableFuture<T>>
和之间的转换CompletableFuture<Stream<T>>
)。
Observable和Stream之间存在显着差异:
Stream#parallel()
将序列划分为多个分区,Observable#subscribeOn()
而Observable#observeOn()
不是;Stream#parallel()
用Observable 模拟行为是很棘手的,它曾经有.parallel()
方法,但是这种方法引起了很大的混乱,以至于将.parallel()
支持转移到github上的单独存储库RxJavaParallel上。更多细节在另一个答案中。Stream#parallel()
不允许指定要使用的线程池,这与大多数接受可选Scheduler的RxJava方法不同。由于JVM中的所有流实例都使用相同的fork-join池,因此添加.parallel()
会意外地影响程序的另一个模块中的行为Observable#interval()
,Observable#window()
和其他许多人; 这主要是因为流是基于拉的,并且上游无法控制何时向下游发射下一个元素takeWhile()
,takeUntil()
); 解决方法的使用Stream#anyMatch()
受到限制:这是终端操作,因此每个流最多只能使用一次Observable#using()
);您可以使用它包装IO流或互斥量,并确保用户不会忘记释放资源-在订阅终止时会自动将其释放;Stream有onClose(Runnable)
方法,但是您必须手动或通过try-with-resources调用它。例如 您必须记住,Files#lines()必须包含在try-with-resources块中。综述:RxJava与Streams明显不同。真正的RxJava替代品是ReactiveStreams的其他实现,例如Akka的相关部分。
更新。可以使用非默认的fork-join池Stream#parallel
,请参见Java 8并行流中的自定义线程池
更新。以上所有内容均基于RxJava 1.x的经验。现在RxJava 2.x在这里,这个答案可能已经过时了。
Stream.generate()
并传递自己的Supplier<U>
实现,这只是一个简单的方法,您可以从中提供流中的下一项。还有许多其他方法。为了轻松构造Stream
依赖于先前值的序列,您可以使用interate()
方法,每个方法Collection
都有一个stream()
方法,并从varargs或数组Stream.of()
构造a Stream
。最后, StreamSupport
它支持使用分隔符创建更高级的流或支持流原始类型。
Java 8 Stream和RxJava看起来非常相似。它们具有相似的运算符(过滤器,地图,flatMap ...),但并非为相同的用途而构建。
您可以使用RxJava执行asynchonus任务。
使用Java 8流,您将遍历集合中的项目。
您可以在RxJava(集合中的遍历项)中执行几乎相同的操作,但是,由于RxJava专注于并发任务,...它使用同步,闩锁,...因此,使用RxJava进行同一任务可能会比Java 8流。
可以将RxJava与进行比较CompletableFuture
,但是它可以计算多个值。
parallelStream
支持简单遍历类似的同步/ MAPS /过滤等。
在技术和概念上存在一些差异,例如,Java 8流是一次性使用的,基于拉的同步值序列,而RxJava Observable是可重新观察的,基于自适应推挽的,潜在的异步值序列。RxJava面向Java 6+,也可在Android上运行。
Java 8 Streams是基于pull的。您遍历消耗每个项目的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 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流或Clojure惰性seq。
Java 8 Streams可以利用多核体系结构有效地处理非常大的集合。相反,默认情况下,RxJava是单线程的(没有调度程序)。因此,除非您自己编写逻辑代码,否则RxJava将不会利用多核计算机。