RxJava运算符

In this tutorial, we’ll discuss and implement the various operators that RxJava has. How each operator transforms the Observable sequences and what the subscriber sees? Let’s start!

在本教程中,我们将讨论和实现RxJava拥有的各种运算符。 每个运营商如何转换可观察序列以及订户看到的内容? 开始吧!

RxJava运算符 (RxJava Operators)

As we had seen in the first RxJava tutorial, Operators are something that acts on an Observable and passes the transformed data to the Subscribers. With multiple operators, each operator finishes its own task and then passes the transformed data to the next operator.

正如我们在第一篇RxJava教程中所看到的,运算符是对Observable起作用的对象,并将转换后的数据传递给Subscriber。 使用多个运算符,每个运算符都会完成自己的任务,然后将转换后的数据传递给下一个运算符。

Create a new IntelliJ Java Project and add the RxJava dependency to get started. We’ll use functional programming and lambdas to make the code simpler and less verbose.

创建一个新的IntelliJ Java项目并添加RxJava依赖关系以开始使用。 我们将使用函数式编程和lambda来使代码更简单,更省力。

1.地图和过滤器 (1. map and filter)

map()

地图()

import rx.Observable;

public class RxOperators {

    public static void main(String[] args)
    {
        
        //map operator
        Observable<String> mapObservable = Observable.just("hello world","the observable emits lower case sentences","subscriber sees it as upper case","map operator");
        mapObservable.map(String::toUpperCase).subscribe(System.out::println);
    }
}
//Prints 
//HELLO WORLD
//THE OBSERVABLE EMITS LOWER CASE SENTENCES
//SUBSCRIBER SEES IT AS UPPER CASE
//MAP OPERATOR

filter()

过滤()

//filter operator
        Observable<String> filterObservable = Observable.from(new String[]{"Hello","How are you?", "doing"});
        filterObservable.filter(string->string.contains(" ")).subscribe(System.out::println);


//Prints
//How are you?

Using Map and Filter : To return the square of all the even numbers.

使用Map和Filter :返回所有偶数的平方。

//map and filter
Observable<Integer> mapFilter = Observable.range(0,10);
mapFilter.filter(i-> i%2==0).map(i-> i*i).subscribe(System.out::println);

2.采取,计数和跳过 (2. take, count and skip)

take operator has three main variants. Let’s look at each of them.

算符有三个主要变体。 让我们看看它们中的每一个。

  • take() passes the first n items emitted by the Observable.

    take()传递Observable发出的前n个项目。
  • takeFirst() emits the first item that meets the condition specified in the operator.

    takeFirst()发出满足运算符中指定条件的第一项。
  • takeLast() prints the last n items. Just the opposite of take()

    takeLast()打印最后n个项目。 与take()相反
  • takeUntil() emits items until a second observable doesn’t start emitting values. Alternatively, it can be used for conditions as well.

    takeUntil()发出项目,直到第二个observable不再开始发出值。 另外,它也可以用于条件。
  • takeWhile() emits items as long as a condition is true. It ignores the remaining.

    只要条件为真, takeWhile()就会发出项目。 它忽略其余的。
Observable<Integer> takeObservable = Observable.range(0,100); 
takeObservable.take(5).subscribe(System.out::println); //prints 0 to 4 
takeObservable.takeFirst(i -> i*i>1000).subscribe(System.out::println); //prints 32
takeObservable.takeLast(1).subscribe(System.out::println); //prints 99

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Observable<Integer> takeUntilObservable = Observable.from(numbers);
takeUntilObservable.takeUntil(number -> number>2)
                   .subscribe(System.out::println); //prints 1 to 3

takeObservable.takeWhile(number -> number<4)
                .subscribe(System.out::println); //prints 1 to 3
takeObservable.takeWhile(number -> number>2)
                .subscribe(System.out::println); //prints nothing

The takeFirst() function prints the first value whose square is greater than 1000.
The takeUntil() operator is like a do-while loop. It first prints the statement before checking for the condition for the next iteration.

takeFirst()函数打印平方大于1000的第一个值。
takeUntil()运算符就像一个do-while循环。 在检查下一次迭代的条件之前,它首先打印该语句。

As the name says, count() returns the number of values that reach the subscriber.

顾名思义, count()返回到达订户的值的数量。

Observable<String> countObservable = Observable.from(new String[]{"First","Second", "Third", "Seventh"});
countObservable.filter(string-> string.length()>5).count().subscribe(System.out::println); //prints 2

Passing null as one of the values would cause a runtime crash in the above case. Hence we need to specify the action for onError()

在上述情况下,将null作为值之一传递将导致运行时崩溃。 因此,我们需要为onError()指定操作

Observable<String> countObservable = Observable.from(new String[]{"First","Second", "Third", null});
countObservable.filter(string-> string.length()>5).count().subscribe(System.out::println, throwable -> System.out.println("One of the values is not valid"));

//prints 
//One of the values is not valid

skip operator has a few variants that are described and implemented below

skip运算符具有以下描述和实现的一些变体

  • skip() ignores the first n values.

    skip()忽略前n个值。
  • skipLast() ignored the last n values

    skipLast()忽略了最后n个值
  • skipWhile() ignores all the values until a specific condition is met. It emits all the remainder of values.

    skipWhile()忽略所有值,直到满足特定条件为止。 它发出所有剩余的值。
  • skipUntil() ignores all the values until another observable starts emitting. We’ll look at this later

    skipUntil()忽略所有值,直到另一个可观察到的值开始发射为止。 我们稍后再看
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        Observable<Integer> skipObservable = Observable.from(numbers);
        skipObservable.skip(3).subscribe(System.out::println); //prints 4 and 5
        skipObservable.skipLast(3).subscribe(System.out::println); //prints 1 and 2
        skipObservable.skipWhile(i-> i<3).subscribe(System.out::println); prints 3 4 and 5

skip is somewhat the opposite of take.

略过与走相反。

skip is the ideal operator to use when avoiding null values.

skip是避免空值时理想的运算符。

3. startWith,reduce,重复,扫描 (3. startWith,reduce, repeat, scan)

startWith() appends the given element at the start of the emission.

startWith()在发射开始时追加给定元素。

Observable<String> startWithObservable = Observable.just(" Rx", "Java", " Operators", " Tutorial");
        startWithObservable.startWith("Welcome to the").subscribe(System.out::print);

//Prints
//Welcome to the RxJava Operators Tutorial

reduce() operator acts as an accumulator. It adds a the next value to previously added values.
Finally prints the accumulated value for the subscriber.

reduce()运算符充当累加器。 它将下一个值添加到先前添加的值。
最后为订户打印累计值。

Observable<Integer> reduceObservable = Observable.range(1, 5);
reduceObservable.reduce((integer, integer2) -> integer + integer2).subscribe(System.out::println);

In the above code, for the first emission, integer is 1 integer2 is 2, for the second emission, 3 and 3 respectively and so on.

在上面的代码中,对于第一次发射,integer是1 integer2是2,对于第二次发射,分别是3和3,依此类推。

reduce operator is useful for calculating the sum, appending strings etc.
The following code finds the length of the concatenated strings.

reduce运算符对于计算总和,附加字符串等很有用。
以下代码查找级联字符串的长度。

Observable<String> reduceStringObservable = Observable.just("Rx", "Java");
reduceStringObservable.reduce((x, y) -> x + y).map(String::length).subscribe(System.out::println);

repeat operator repeats the emission twice.

重复运算符重复发射两次。

Observable.just("Android", "iOS", "Windows")
                .repeat(2)
                .subscribe(System.out::println);

//Prints
//Android
//iOS
//Android
//iOS

scan operator unlike reduce, prints the accumulator value incrementally

scan运算符与reduce不同,它增量打印累加器值

Observable.range(1, 5).scan((integer, integer2) -> integer + integer2).subscribe(System.out::println);

//prints
1
3
6
10
15

4.全部,包含,elementAt (4. all, contains, elementAt)

The all() operator checks whether each value meets the condition. It returns a true/false.

all()运算符检查每个值是否满足条件。 返回true / false。

Observable.range(1, 5).all(i-> i%2==0).subscribe(System.out::println);//prints false
Observable.range(1, 5).map(i-> i*2).all(i-> i%2==0).subscribe(System.out::println); //prints true

contains(): It checks if the value mentioned exists in the Observable lot.

contains() :检查可观察批次中是否存在提及的值。

Observable.range(1, 5).contains(6).subscribe(System.out::println); //prints false
Observable.range(1, 5).contains(4).subscribe(System.out::println); //prints true

elementAt() : It prints the value present at the given index among the list of emitted values.

elementAt() :打印输出值列表中给定索引处的值。

Observable.range(1, 5).elementAt(4).subscribe(System.out::println); //prints 5

5.与众不同,toList,toSortedList (5. distinct, toList, toSortedList)

distinct() operator eliminates duplicate values.

distinct()运算符可消除重复值。

Observable.just(1,2,3,1,5,1,2,3).count().subscribe(System.out::println); //prints 8
Observable.just(1,2,3,1,5,1,2,3).distinct().count().subscribe(System.out::println); //prints 4

toList and toSortedList are used to convert the emission into another observable that is of the type list.
toSortedList sorts the emission in ascending order.
We can also set our own comparator to sort.

toListtoSortedList用于将发射转换为另一个可观察到的类型列表。
toSortedList按升序对发射进行排序。
我们还可以设置自己的比较器进行排序。

Observable.just(1, 2, 3, 1, 5, 1, 2, 3).toList().subscribe(System.out::println);
Observable.just(1, 2, 3, 1, 5, 1, 2, 3).toSortedList().subscribe(System.out::println);
Observable.just(1, 10, 20, 2).toSortedList((integer, integer2) -> integer2 < integer ? -1 : integer == integer2 ? 1 : 0).subscribe(System.out::println);

//prints
//[1, 2, 3, 1, 5, 1, 2, 3]
//[1, 1, 1, 2, 2, 3, 3, 5]
//[20, 10, 2, 1]

In the above code, the third observable sorts the values in descending order.

在上面的代码中,第三个可观察值按降序对值进行排序。

6. concat,合并,zip (6. concat, merge, zip)

concat is used to concatenate observables without interleaving them.
merge is used to concatenate observables by interleaving them
That means that in concat the new observable would contain the first followed by the second.
In merge they can be mixed, depending on when they arrive.

concat用于连接可观察对象而不交错它们。
merge用于通过插入可观察对象来连接它们
这意味着在concat ,新的可观察对象将包含第一个,然后是第二个。
merge它们可以混合在一起,具体取决于它们何时到达。

Observable.concat(
                Observable.interval(1, TimeUnit.SECONDS).map(id -> "CA" + id),
                Observable.interval(1, TimeUnit.SECONDS).map(id -> "CB" + id))
                .subscribe(System.out::println);

        Thread.sleep(5000);

//Prints:
//CA0
//CA1
//CA2
//CA3
//CA4

Note: We need to add a sleep to prevent early exit of the main function.
In the concat() method, until the first observable isn’t done it won’t move to the second.
So in the above code, the second doesn’t get printed since the first observable prints its quota in the 5 seconds.
Let’s set a limit on the first using take.

注意:我们需要添加睡眠以防止主要功能提前退出。
在concat()方法中,直到第一个可观察到的对象没有完成,它才移至第二个。
因此,在上面的代码中,第二个未打印,因为第一个可观察到的字符在5秒钟内打印了配额。
让我们为第一个使用take设置一个限制。

Observable.concat(
                Observable.interval(1, TimeUnit.SECONDS).take(2).map(id -> "CA" + id),
                Observable.interval(1, TimeUnit.SECONDS).map(id -> "CB" + id))
                .subscribe(System.out::println);

        Thread.sleep(5000);

//prints 
CA0
CA1
CB0
CB1
CB2

merge two observables

合并两个可观察对象

Observable.merge(
                Observable.interval(1, TimeUnit.SECONDS).map(id -> "MA" + id),
                Observable.interval(1, TimeUnit.SECONDS).map(id -> "MB" + id))
                .subscribe(System.out::println);

        Thread.sleep(5000);

//prints 
MB0
MA0
MB1
MA1
MA2
MB2
MB3
MA3
MA4
MB4

As you can see merge interleaves them. But it doesn’t guarantee the sequence of emission.

如您所见,合并使它们交错。 但这不能保证发射的顺序。

merge and concat above work on Observables only.
To make them work as operators we need to use mergeWith and concatWith

mergeconcat上述工作只观测量。
为了使它们作为运算符起作用,我们需要使用mergeWithconcatWith

Observable sourceA = Observable.interval(1, TimeUnit.SECONDS).map(id -> "MA" + id);
Observable sourceB = Observable.interval(1, TimeUnit.SECONDS).map(id -> "MB" + id);

sourceB.mergeWith(sourceA).subscribe(System.out::println);
Thread.sleep(5000);

Use concatWith in the above code to get the relevant operator for concat.

在上面的代码中使用concatWith获得concat的相关运算符。

zip is used to pair each emission from each of the observables. Each observable would wait for the others to emit the current value and then each of the values is available for you in a function.
zip is useful to concatenate different types.

zip用于将每个可观测对象的每个发射配对。 每个可观察值将等待其他可观察值发出当前值,然后在函数中可以使用每个值。
zip可用于连接不同类型。

Observable.zip(
                Observable.interval(1, TimeUnit.SECONDS).map(id -> String.valueOf( (char)(id + 65))),
                Observable.interval(2, TimeUnit.SECONDS), (s1, s2) -> s1 + s2)
                .subscribe(System.out::println);

        Thread.sleep(9000);

//prints
//A0
//B1
//C2
//D3

In the above code, the first observable emits an integer every second. The map operator converts the integer to the relevant character using the ASCII code and returns it as a string.
The second observable emits an integer every two seconds. So the first observable needs to wait for this.

在上面的代码中,第一个可观察对象每秒发射一个整数。 映射运算符使用ASCII码将整数转换为相关字符,并将其作为字符串返回。
第二个可观察对象每两秒钟发出一个整数。 因此,第一个可观察到的需要等待。

Try implementing the zipWith operator yourself. It’s analogous to concatWith and mergeWith.

尝试自己实现zipWith运算符。 与concatWithmergeWith类似。

7.防抖,延迟 (7. debounce, delay)

A debounce operator only emits an item from an Observable if a particular timespan has passed without it emitting another item. This operator is really useful in places like EditText in a SearchView in Android.
Typically entering anything, the search view would call a backend API with the current text. Using the debounce operator saves the immediate call. It gives the user a time to assess the text they’ve entered and whether they’re looking to modify it. Only after the certain timespan is passed the backend API would be called!

debounce运算符仅在经过特定时间范围后才从Observable发出一项,而不发出另一项。 这个运算符在Android的SearchView中的EditText等地方非常有用。
通常,输入任何内容后,搜索视图都会使用当前文本调用后端API。 使用反跳运算符可以保存即时呼叫。 它使用户有时间评估他们输入的文本以及他们是否要修改它。 只有经过特定的时间跨度后,才会调用后端API!

Observable.just(1,2,3,4,5,6)
                .debounce(1, TimeUnit.SECONDS)
                .subscribe(System.out::println, System.out::println, () -> System.out.print("OnComplete"));
//Prints 6

The last element is printed in the cases like above since there is nothing left and the debounce operator emits the value after the delay.

在上述情况下,最后一个元素将被打印,因为没有剩余任何内容,并且反跳运算符在延迟后发出该值。

The delay operator delays the start of emission of values from the Observable by a certain time.

delay运算符将从Observable发射值的开始延迟一定时间。

Observable.just(1,2,3,4,5,6)
                .delay(5, TimeUnit.SECONDS)
                .subscribe(System.out::println, System.out::println, () -> System.out.print("OnComplete"));

        Thread.sleep(4000);

In the above code, nothing happens since our main function would return after 4 seconds thereby preventing the emission that was to occur after 5 seconds.

在上面的代码中,什么都没有发生,因为我们的main函数将在4秒后返回,从而防止5秒后发生发射。

This brings an end to this tutorial. We’ve covered some major operators. You can download the RxJavaOperators Project source code from the link below.

本教程到此结束。 我们已经介绍了一些主要的运营商。 您可以从下面的链接下载RxJavaOperators Project源代码。

翻译自: https://www.journaldev.com/19254/rxjava-operators

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值