RxJava:计数或时间范围内的窗口,不丢弃元素

时间:2014-08-06 16:31:04

标签: rx-java

我希望按照一定的最大尺寸分割我的流,如果在一段时间后没有达到这个尺寸,请关闭批次并开始一个新的。 为此,我尝试使用窗口(计数):

things.window(10)

然而,这会等到收到10个元素才能发出新的Observable窗口。 如果我使用窗口(时间跨度,单位,计数)运算符:

things.window(1, TimeUnit.SECONDS, 10)

我将放弃在10日之后和时间跨度完成之前的所有元素。

我喜欢类似的操作符,而不是等到时间跨度完成时,在计数到达时会发出新的窗口。

things.windowXXX(timespan = 1s, count = 2) : Observable[T]

things:   ----o--o--o-----------o----o------->
timespan: [      )[    1s    ][      )[    -->
window 1: -----o-o-|
window 2:          -o---------|
window 3:                     --o-----o-| 

1 个答案:

答案 0 :(得分:5)

我找到了一种方法来解决此问题,方法是使用缓冲区(timespan,timeunit,count)而不是窗口。 我认为缓冲区和窗口只有一个发出列表和其他可观察对象的行为相同。但似乎这里存在差异。

我的解决方案是使用缓冲区,然后将每个结果映射到一个observable:

observable.buffer(10, TimeUnit.MILLISECONDS, 2)
          .map(new Func1<List<String>, Observable<String>>() {
                public Observable<String> call(List<String> l) {
                    return Observable.from(l);
                }
           })

我做了一些测试,看看差异:https://gist.github.com/jcfandino/fd47277ada821f51a9d4

    observable.map(delayOn4).window(10, TimeUnit.MILLISECONDS, 2)
            .subscribe(new UpdateCountdowns("window"));
    assertTrue(itemsCount.await(100, TimeUnit.MILLISECONDS));
    assertTrue(batchesCount.await(100, TimeUnit.MILLISECONDS));

打印:

  

窗口 - 1968827463:1
  窗口 - 1968827463:2
  窗口 - 1968827463:3
  窗口 - 1267747034:4
  窗口 - 1267747034:5

请注意,它会发出两个批次而不是三个,第一个有三个元素而不是两个。

另一方面,使用缓冲区

    observable.map(delayOn4).buffer(10, TimeUnit.MILLISECONDS, 2)
            .map(new Func1<List<String>, Observable<String>>() {
                public Observable<String> call(List<String> l) {
                    return Observable.from(l);
                }
            }).subscribe(new UpdateCountdowns("buffer"));
    assertTrue(itemsCount.await(100, TimeUnit.MILLISECONDS));
    assertTrue(batchesCount.await(100, TimeUnit.MILLISECONDS));

打印:

  

缓冲区 - 1257525795:1
  缓冲区 - 1257525795:2
  缓冲区 - 1849466438:3
  缓冲区 - 104886386:4
  缓冲区 - 104886386:5

三个批次最多包含两个元素,作为&#34; 4&#34;到了很晚,它在下一批结束了。

我不知道这是否是预期的行为,或者可能存在错误。