如何使用RxJava从另一个流实现过滤器

时间:2017-04-18 16:01:26

标签: rx-java rx-java2

所以我有两个像这样的蒸汽:

--1--2--3--4--5--6-|
-----A-----B-------|

我的目标是拥有像这样的流

--1----3------5--6-|

我尝试使用像takeUntil或skipUntil这样的运算符但是我无法生成有效的东西。你能给我一些帮助吗?

由于

2 个答案:

答案 0 :(得分:2)

通常,2和A之间存在重合问题,您必须定义一个窗口,其中第二个流可以阻止发出第一个值。例如,这将等待每个项目1毫秒(2.x):

import java.util.concurrent.TimeUnit;

import io.reactivex.*;
import io.reactivex.schedulers.TestScheduler;

public class Coincidence {

    public static void main(String[] args) {
        TestScheduler sch = new TestScheduler();

        Flowable.interval(100, TimeUnit.MILLISECONDS, sch)
        .onBackpressureBuffer()
        .compose(coincide(Flowable.interval(300, TimeUnit.MILLISECONDS, sch), sch))
        .take(7)
        .subscribe(v -> 
            System.out.printf("%d - %d%n", sch.now(TimeUnit.MILLISECONDS), v));

        sch.advanceTimeBy(1001, TimeUnit.MILLISECONDS);
    }

    static <T, U> FlowableTransformer<T, T> coincide(
            Flowable<U> other, Scheduler scheduler) {
        return f -> {
            return other.publish(g -> {
                return f.flatMap(v -> {
                    return Flowable.just(v)
                            .delay(1, TimeUnit.MILLISECONDS, scheduler)
                            .takeUntil(g)
                    ;
                }, 1)
                .takeUntil(g.ignoreElements())
                ;
            });
        };
    };
}

答案 1 :(得分:0)

如果你需要处理“巧合”,我认为akarnokd给出了唯一可行的解​​决方案。

顺便说一句,在大多数情况下,您可能不需要同时或在特定的时间窗口中发生事件,但您只需要在项目发出之前检查某个事件是否发生。例如,您的方案可以像这样调整:

--1-----2----3------4------5--6-|
-------A----------B-------------|

这意味着A(发生在2之后)会阻止它通过。对于4和B也是如此。

如果是这种情况,我会按如下方式解决: 合并两个Observables,然后使用扫描确定哪个项目应传播到下游,最后过滤结果。

 Observable.merge(Observable.just(1, 2, 3, 4, 5, 6).map(integer -> new ValueObject(integer)),
        Observable.just("A", "B").map(string -> new BarrierObject(string)))
        .scan((myObject, myObject2) -> {
            if (myObject instanceof BarrierObject) {
                myObject2.setFilter();
            }

            return myObject2;
        })
        .filter(myObject -> (myObject instanceof ValueObject) && myObject.isValid())
        .map(myObject -> (Integer) myObject.getValue())
        .subscribe(integer -> Log.d("test", "value: " + String.valueOf(integer)));

ValueObjectBarrierObject扩展了以下类:

abstract class MyObject {
    boolean toBeFiltered;
    Object value;

    public void setFilter() {
        toBeFiltered = true;
    }

    public boolean isValid() {
        return !toBeFiltered;
    }

    public Object getValue() {
        return value;
    }
}