java stream优点_在Java 8 Stream上使用RXJava的优点

java stream优点

Java 8流使我作为软件工程师的编程工作变得更加简单。 但是,通过合并RXJava库,还有很多可以改进的地方。 RXJava包含大量处理流或可观察对象的功能。

在Java 9中,有一个类似的概念称为Flow [3]。 如果您正在考虑升级到Java 9或已经在使用Java 9,但尚未使用React式流编程概念,那么您可能需要事先尝试流程概念。

在本文中,我将重点介绍一部分RXJava功能,这些功能在我的代码中将是最有用的。 我不会介绍RXJava的所有功能,因为那太长了。 有关RXJava功能的更多信息,请阅读[1]。

使用Zip运算符轻松组合两个流

有时,有些情况下您想在两个Collection之间一起进行迭代。 假设您有两个整数列表,并且想要“组合”列表1中具有相同索引的每个元素与列表2中的每个元素。那么您可能会想到这样的代码。

List list1 = IntStream.range(0 , 10 )
        .boxed()
        .collect(Collectors.toList());
List list2 = IntStream.range( 1 , 11 )
        .boxed()
        .collect(Collectors.toList());

for ( int i = 0 ; i < list1.size(); i++) {
  System.out.println(list1.get(i) + list2.get(i));
}

在python中,有一个名为zip的运算符,它使这段代码更短,幸运的是,我也可以使用RXJava的zip运算符来做到这一点!

Observable.zip(
            Observable.range(0 , 10 ), 
            Observable.range( 1 , 11 ), 
            (x, y) -> x + y)
        .subscribe(System.out::println);

易于重用的流/可观察

Java流被设计为只能使用一次。 如果您想知道为什么在stackoverflow [2]上对此有很好的解释,但是我在这里不做介绍。

现在,考虑这个例子

Stream intStream = IntStream.range(0 , 10 ).boxed();
intStream.forEach(System.out::println);
intStream.forEach(System.out::println);

此代码将打印从0到10的整数,但是将出现以下异常。

java.lang.IllegalStateException:流已被操作或关闭

Java 8流不应该多次使用。 据我了解,此行为背后的原因是非单发源和单发源的迭代器之间的统一行为[2]。 在一次读取的源代码中,就像从文件中读取行一样,很难确定是否需要重复两次的情况该怎么办?

使用Java 8流,您必须重新启动流才能使其正常工作。

Stream intStream = IntStream.range(0 , 10 ).boxed();
intStream.forEach(System.out::println);
intStream = IntStream.range( 0 , 10 ).boxed();
intStream.forEach(System.out::println);

RXJava编程概念的假设不同于Java 8流,因此允许我们重用Collection的流。

Observable intObservable =  Observable.range(0 , 10 );
intObservable.subscribe(System.out::println);
intObservable.subscribe(System.out::println);

简易错误处理

考虑另一个例子。 您想进行除法运算,并使用-4到5之间的整数作为分母。

IntStream.range(-4 , 5 )
        .map(i -> 1 / i)
        .forEach(System.out::println);

您会注意到在某些情况下,在流的中间将计算1/0 ,这将引发错误

java.lang.ArithmeticException:/减零

现在您有两种选择

  1. 更改流值以手动排除0。为此,您可以使用filter(i != 0)流操作。
  2. 更改map功能,也许要使用try... catch... 好的,我对你说老实话, 这个选项很烂

在这种情况下,您可以轻松选择选项1,但在实际情况下则不能 。 在实际情况下,您很可能会选择选项2 。 您甚至都不知道导致错误的值是什么。 或者,如果您知道引起错误的值,则需要考虑将多少个值硬编码到过滤器操作中。 也许放置错误处理功能会更容易。

幸运的是,RXJava将帮助您处理这种错误情况,而无需编写try-catch块! 没有filter功能,您可以通过以下几种方法处理导致错误的不想要的值。

附加错误订阅

subscription subscribe()可能需要附加订阅来处理发生错误的情况,例如:

Observable.range(-4 , 5 )
        .map(i -> 1 / i)
        .subscribe(
                System.out::println,
                t -> System.out.println( "some error happened" ));

此代码块将打印“发生了一些错误”,因为它仍将尝试执行1/0 ,尽管现在不会引发异常。

错误时替换值

使用onErrorReturnItem() 发生错误时提供默认值

Observable.range(-4 , 5 )
        .map(i -> 1 / i)
        .onErrorReturnItem(- 1 )
        .subscribe(
                System.out::println, 
                t -> System.out.println( "some error happened" ));

使用onErrorReturnItem()时需要多加注意。 此代码不会调用错误订阅函数,因为发生错误后它将用-1替换值。 这意味着, 无论下一个值是否产生错误,0之后的值都将由-1代替

结论

RXJava有许多简化流代码的方法,但这并不是它唯一的功能。 本文尚未讨论RXJava的其他令人兴奋的功能,例如如何处理“热”或“冷”可观察对象,如何处理背压或如何并行化操作。 我鼓励读者探索更多关于React式概念的知识,并深入RXJava库以体验和思考使您的应用程序成为React式的。

参考资料

[1] Samoylov,N.,Nield,T。2020。《学习RxJava第二版》。

[2] https://stackoverflow.com/questions/28459498/why-are-java-streams-once-off/28513908#28513908

[3] Java 9React流。 https://www.baeldung.com/java-9-reactive-streams

翻译自: https://hackernoon.com/advantages-of-using-rxjava-over-java-8-stream-q82a3whh

java stream优点

你可能感兴趣的:(python,java,机器学习,大数据,编程语言)