带去抖动的RxJava2缓冲区

时间:2018-04-16 18:25:12

标签: java rx-java2

我希望缓冲元素并在x时间内没有新元素时将它们作为集合发出。怎么做?

例如给定输入

INPUT    TIME
1        0  
2        0
3        100
4        150
5        400
6        450
7        800   

如果我的x = 200,我想发出{1, 2, 3, 4}, {5, 6}, {7}

我尝试的是简单buffer()随着时间的推移,但它没有提供去抖动。我还在源throttleFirst()上尝试了flatMap(),在buffer().take(1)内的源flatMap上尝试了org.springframework.expression.spel.SpelEvaluationException: EL1027E:(pos 13): Indexing into type 'org.springframework.batch.core.JobParameters' is not supported ,它的工作原理类似,但并不完全符合要求。

1 个答案:

答案 0 :(得分:5)

您需要publish,因为您需要相同的来源来通过去抖动来控制缓冲行为:

static <T> ObservableTransformer<T, List<T>> bufferDebounce(
        long time, TimeUnit unit, Scheduler scheduler) {
    return o ->
        o.publish(v -> 
            v.buffer(v.debounce(time, unit, scheduler)
                .takeUntil(v.ignoreElements().toObservable())
            )
        );
}

@Test
public void test() {
    PublishSubject<Integer> ps = PublishSubject.create();

    TestScheduler sch = new TestScheduler();

    ps.compose(bufferDebounce(200, TimeUnit.MILLISECONDS, sch))
    .subscribe(
            v -> System.out.println(sch.now(TimeUnit.MILLISECONDS)+ ": " + v),
            Throwable::printStackTrace,
            () -> System.out.println("Done"));

    ps.onNext(1);
    ps.onNext(2);

    sch.advanceTimeTo(100, TimeUnit.MILLISECONDS);

    ps.onNext(3);

    sch.advanceTimeTo(150, TimeUnit.MILLISECONDS);

    ps.onNext(4);

    sch.advanceTimeTo(400, TimeUnit.MILLISECONDS);

    ps.onNext(5);

    sch.advanceTimeTo(450, TimeUnit.MILLISECONDS);

    ps.onNext(6);

    sch.advanceTimeTo(800, TimeUnit.MILLISECONDS);

    ps.onNext(7);
    ps.onComplete();

    sch.advanceTimeTo(850, TimeUnit.MILLISECONDS);
}

takeUntil用于阻止o完成触发空缓冲区。