到目前为止,我们看到的例子都还比较小,在这里,我们将探索可以过滤掉不相关数据或将数据简化为所需的单个值。
这里的大多数操作符对于任何熟悉Java流或函数编程的人来说都是熟悉的。这里的所有 operators 都返回一个新的observable,并且不影响原始的可观测性。这一原则在整个 Rx 中都存在。observables 转换每一次都会产生一个新的 observable ,并且保持原始的不受影响。原始 observable 的 Subscribers 应该不会注意到任何变化,但是我们将在后面的章节中看到,保证这一点可能需要开发人员引起注意。
Marble diagrams
这是一个适当的时间引入 marble diagrams 的概念。这是解释Rx中的 operators 的一种流行方法,因为它们的直观和图形性质。它们在 RxJava 的文档中有很多,我们只有利用它们的解释性质。格式基本上是不言自明的:时间从左向右流动,形状表示值,斜杠是一个o nCompletion,X 是一个错误。运算符应用于顶部 sequence,结果是下面的 sequence 。
Filter
Filter接受一个谓词函数,该谓词函数对发出的每个值做出一个布尔决策。如果判定为false,则筛选序列中省略该项。
public final Observablefilter(Func1 predicate)
我们将使用过滤器创建一个数字序列,并过滤掉所有偶数,只保留奇数。
输出:
distinct and distinctUntilChanged
distinct 筛选出去重的任何元素。
输出:
一个 distinct 的重载需要一个 key 选择器。对于每个项,函数生成一个键,然后使用键来确定。
在这个例子中,我们使用第一个字符作为一个 key。
输出:
“Fourth”和“Fifth”被过滤掉,因为它们的第一个字符是‘f’,它已经出现在“First”。
有经验的程序员已经知道,这个 operator 在内部维护一个 set,每个唯一的值都通过 observable 的值传递,并根据它检查每个新的值。虽然 Rx 操作符巧妙地隐藏了这些东西,但您仍然应该意识到 Rx 操作符可能会有很大的成本,并考虑您正在使用它的内容。
distinctUntilChanged 和 distinct 不同之处在于,只有连续的不同的值才会被过滤掉。
输出:
distinctUntilChanged 也可以使用 key selector。
输出:
ignoreElements
ignoreElements会忽略每一个值,但是让我们通过onCompleted和onError。
输出:
ignoreElements() 的作用和 filter(v -> false) 类似。
skip and take
下一组方法用于根据项目索引在特定点上按特定点进行顺序操作,或者先取第一部分或第二个子元素。take 取前 n 个元素,skip 是跳过他们,注意,如果序列中的项少于指定索引,则两个函数都认为它是错误。
输出:
java 8 stream 的使用者应该知道 limit 的操作符,在rx中也存在这样的运算符,take 就是这样一个别名,我们很快也会看到更多的重载方法。
一旦第n项可用,take 方法立即完成.。如果发生错误,错误将被转发,但如果发生在切点之后,take 方法则不会关心。
输出:
skip 返回 take 的另一半:
输出:
这里有些重载方法限制了时间
输出:
skipWhile and takeWhile
take 和 skip 使用预定义索引工作。如果您想要“发现”截止点,当值出现时,takeWhile和skipWhile将使用谓词。
ObservabletakeWhile(Func1 predicate)
输出:
如你所想的一样,skipWhile 返回另一半:
输出:
skipLast and takeLast
skipLast 和 takeLast 作用类似于 take 和 skip ,不同之处在于结束的位置:
输出:
takeUntil and skipUntil
还有两种方法:takeUntil和skipUntil。takeUntil工作完全类似于takeWhile谓词返回false的情况,skipUntil是true的情况。
除此之外,takeUntil 和 skipUntil 都有一个非常有趣的重载,临界点被定义为另一个 observable 发射一个值时。
输出:
您可能还记得,这里的计时器将等待250 ms并发出一个事件。这意味着要停止序列。请注意,信号可以是任何类型的,因为实际值不被使用。
skipUntil 按照相同的规则工作,并返回 observable 另一半。值被忽略直到信号开始让值通过。
输出: