Rx java rxJava与throttleFirst运算符相反(不是节流而是收集)

Rx java rxJava与throttleFirst运算符相反(不是节流而是收集),rx-java,reactive-programming,rx-java2,Rx Java,Reactive Programming,Rx Java2,我需要以下运算符,当元素出现时,该运算符启动计时器(为元素创建窗口)并将它们收集到列表中或可观察/可流动。当为计时器指定的时间结束且没有元素出现时,操作员不会发送空事件。当下一个元素出现时,将创建新的计时器并开始收集元素 Rx java有缓冲区和窗口操作符,但这种操作符有缺点: 缓冲区 签名 buffer(longtimespan,TimeUnit)几乎适合,但当timespan中没有元素时,它会生成带有空列表的事件 窗口 签名 窗口(长时间跨度,时间单位)几乎适合,但当时间跨度中没有元素出

我需要以下运算符,当元素出现时,该运算符启动计时器(为元素创建窗口)并将它们收集到
列表中
可观察/可流动
。当为计时器指定的时间结束且没有元素出现时,操作员不会发送空事件。当下一个元素出现时,将创建新的计时器并开始收集元素

Rx java有缓冲区和窗口操作符,但这种操作符有缺点:

  • 缓冲区 签名
    buffer(longtimespan,TimeUnit)
    几乎适合,但当timespan中没有元素时,它会生成带有空列表的事件

  • 窗口 签名
    窗口(长时间跨度,时间单位)
    几乎适合,但当时间跨度中没有元素出现时,它会产生空的
    可观测值/可流动值

可以过滤这些空元素,但我希望通过
List/Observable-s/Flowable-s
避免空事件(基于计时器)污染调度程序

我花了一些时间,发现在形式上非常相似,但在功能上实现了相反的角色
throttleFirst(长窗口持续时间,时间单位)


但不幸的是,它会限制,但不会收集项目。

您希望发生什么而不是
onComplete
?能否将
缓冲区()
窗口()
开关ifempty()
组合使用


我不认为可以节省创建对象的时间,所以如果您想避免空列表,请将其过滤掉

至于在新项目迟到时启动新的周期计时器,我想不出任何现有操作符的组合可以在不丢失项目的情况下完成

我创建了以下“精巧装置”,可以在不丢失物品的情况下完成:

公共静态最终类BufferWithTimeout{
Scheduler.Worker trampoline=Schedulers.trampoline().createWorker();
最终长超时;
最终计时单位;
最终调度器。工人;
最终SerialDisposable计时器=新的SerialDisposable();
最终PublishSubject输出=PublishSubject.create();
列示电流;
长缓冲指数;
BufferWithTimeout(长超时、时间单位、调度程序){
this.worker=scheduler.createWorker();
this.timeout=超时;
这个。单位=单位;
}
无效值(T值){
蹦床。时间表(()->{
if(timer.isDisposed()){
返回;
}
如果(当前==null){
当前=新的ArrayList();
长bi=++bufferIndex;
timer.set(worker.schedule)定期(()->{
实时(bi);
},超时,超时,单位);
}
当前.增加(价值);
});
}
void onTime(长索引){
蹦床。时间表(()->{
if(index==bufferIndex&¤t!=null){
if(current.isEmpty()){
电流=零;
bufferIndex++;
定时器设置(空);
}否则{
输出.onNext(当前);
当前=新的ArrayList();
}
}
});
}
终止无效(可丢弃错误){
timer.dispose();
worker.dispose();
蹦床。时间表(()->{
if(current!=null&&!current.isEmpty()){
输出.onNext(当前);
电流=零;
}
if(错误!=null){
输出。onError(错误);
}否则{
output.onComplete();
}
});
}
无效处置(){
timer.dispose();
worker.dispose();
蹦床。时间表(()->{
电流=零;
});
}
公共静态可观测转换器创建(
长超时、时间单位、计划程序){
返回o->
可观察。延迟(()->{
BufferWithTimeout状态=新建BufferWithTimeout(
超时、单位、调度程序);
返回o
.doOnNext(v->state.onValue(v))
.doon错误(e->state.onTerminate(e))
.doOnComplete(()->state.onTerminate(null))
.ignoreElements()
.TooObservable()文件
.mergeWith(state.output.doOnDispose(state::dispose));
});
}
}
您可以通过以下方式尝试:

//随时间生成事件
可观测。从阵列(1,2,3,5,20,21,22,23,24,25,26,27,28,29,30,31)
.flatMap(v->Observable.timer(v*100,TimeUnit.ms).map(w->v))
//应用运算符
.compose(BufferWithTimeout.create(
700,TimeUnit.millizes,Schedulers.computation()
))
//等着吧
.blockingSubscribe(System.out::println);

请注意,虽然这会为每个源元素创建更多的对象,但这是有办法的,但它会变得更加复杂。

是的,我可以只筛选
。筛选(e->!e.isEmpty())
以防缓冲区出现,或者不对空
可观察的
做出反应,但在这种情况下,调度程序正在发送空事件(基于计时器)我想避免这种情况。当我们说“empty”时,我们可能指的是不同的东西——你是说“empty”如“emits a empty list”,还是说“empty”如“source observable fires
onComplete()
”?因为我将您的情况解释为当操作员的时间范围内没有排放时,缓冲区/窗口正在调用
onComplete()
。我指的是空列表。我已经更新了描述。缓冲区不对空事件调用
onComplete()
。缓冲区调用带有空列表的onNext()
。此代码
//No emissions or on complete
source.window(...).switchIfEmpty(Observable.never());
//Empty list emission
source.window(...).switchIfEmpty(Observable.just(Collections.emptyList()));