如何将订阅延迟到另一个发布者发出特定顺序之前?

时间:2018-09-17 05:31:20

标签: java rx-java rx-java2

假设我有一个Flowable<Integer> sequence,它发出编码事件。另一个Flowable<Boolean> task需要延迟,直到sequence发出特定序列为止(例如123)。我该怎么办?

当前,我将task的flowable延迟到发出某个值之前,就像这样:

task = task.delaySubscription(sequence.filter(i -> i == 42));

我尝试使用buffer(3)完成此操作,但是如果发射值的总数不能被3整除,则该方法不起作用。

task = task.delaySubscription(sequence.buffer(3).filter(vals -> vals.get(0) == 1 && vals.get(1) == 2 && vals.get(2) == 3));

// This fails
sequence.onNext(42);
sequence.onNext(1);
sequence.onNext(2);
sequence.onNext(3);
task.test().assertValueCount(1).assertValue(true);

// While this works
sequence.onNext(1);
sequence.onNext(2);
sequence.onNext(3);
task.test().assertValueCount(1).assertValue(true);

我需要同时处理这两种情况;唯一重要的是最近发射的三个物品。

1 个答案:

答案 0 :(得分:0)

也许通过实现自定义过滤器?

private static class SequencePredicate implements Predicate<Integer> {
    private final List<Integer> searchedSequence;
    private LinkedList<Integer> remaining;

    private SequencePredicate(final List<Integer> searchedSequence) {
        this.searchedSequence = searchedSequence;
        this.remaining = new LinkedList<>(searchedSequence);
    }

    @Override
    public boolean test(final Integer integer) throws Exception {
        boolean result = false;

        if (remaining.isEmpty()) {
            result = true;
        } else if (remaining.getFirst().equals(integer)) {
            remaining.removeFirst();
            result = remaining.isEmpty();
        } else if (remaining.size() < searchedSequence.size()) {
            remaining = new LinkedList<>(searchedSequence);
        }
        return result;
    }
}

public static void main(String[] args) {
    Flowable<Integer> sequence = Flowable.just(3, 5, 1, 2, 6, 1, 2, 3, 8, 9);
    // Flowable<Integer> sequence = Flowable.just(3, 5, 1, 2, 6, 1, 2, 8, 9, 10);
    List<Integer> searchedSequence = Arrays.asList(1, 2, 3);

    Flowable<Integer> delayFlowable = sequence.doOnNext(n -> System.out.println("before: " + n))
                                              .filter(new SequencePredicate(searchedSequence))
                                              .doOnNext(n -> System.out.println("after: " + n));

    Flowable<Boolean> task = Flowable.just(true);
    task.delaySubscription(delayFlowable)
        .subscribe(n -> System.out.println("task: " + n),
                   Throwable::printStackTrace,
                   () -> System.out.println("task: that's the end!"));

    Flowable.timer(10, SECONDS) // just for blocking the main thread
            .blockingSubscribe();
}