我有一个热的observable,可以生成不同类型的事件,我想在给定的时间范围内连续发出相同类型的事件,如下所示:
输入:“A1”,“A2”,“A3”,“B1”,“B2”,“A4”,“A5”
输出 :(“A1”,“A2”),(“A3”),(“B1”,“B2”),(“A4”,“A5”)
在上面的例子中,事件“A3”来得太晚,因此没有与事件(“A1”,“A2”)分组。
我怎么能用RxJava做到这一点?
答案 0 :(得分:0)
这可以按照以下方式完成
observable
.scan(new ArrayList<T>(), groupingFunction)
.lift(new DistinctUntilChanged<List<T>>())
其中分组函数在类
之后扩展public abstract class GroupingFunction<T> implements Func2<List<T>, T, List<T>> {
@Override
public List<T> call(List<T> group, T t) {
if (group.isEmpty()) {
group.add(t);
return group;
}
T first = group.get(0);
if (isInSameGroup(first, t)) {
group.add(t);
return group;
} else {
List<T> result = new ArrayList<>();
result.add(t);
return result;
}
}
protected abstract boolean isInSameGroup(T left, T right);
}
此处isInSameGroup
定义分组标准以及项目是否在同一时间范围内(也可以将源可观察源与Observable.interval
合并以包括时间事件,然后可以对其进行反应以生成组)
和DistinctUntilChanged
实现如下
public class DistinctUntilChanged<T> implements Operator<T, T> {
@Override
public Subscriber<? super T> call(final Subscriber<? super T> child) {
return new Subscriber<T>(child) {
T previousHolder = null;
@Override
public void onNext(T cur) {
T prev = previousHolder;
previousHolder = cur;
if (prev != null) {
if (prev == cur) {
request(1);
} else {
child.onNext(prev);
}
} else {
request(1);
}
}
@Override
public void onError(Throwable e) {
child.onError(e);
}
@Override
public void onCompleted() {
if (previousHolder != null) child.onNext(previousHolder);
child.onCompleted();
previousHolder = null;
}
};
}
}
此实现类似于rx.internal.operators.OperatorDistinctUntilChanged
,但使用简单的引用相等性并发出不同的最后一个对象,而不是第一个。
这应该产生连续项目所需的分组。
答案 1 :(得分:0)
感谢您的回答。
我花了一些时间来解决这个问题,最后找到了这个解决方案:
// buffer the events that occur in a given timeframe
observable.buffer(timespan, TimeUnit.MILLISECONDS)
// transform each buffer of events into a list of buffers of events of the same type, while preserving the order of the events
.map(buffer ->
buffer.stream()
.collect(Collectors.groupingBy(
this::getKey,
LinkedHashMap::new,
Collectors.toList())
).values()
)
// flatten the list of buffers into buffers
.flatMapIterable(bufferList -> bufferList)
.subscribe(buffer -> LOGGER.info(buffer));
但这对我来说仍然看起来有点过于复杂。还有其他解决方案吗?