如何用RxJava2嵌套遍历列表并过滤子列表后更新父对象?
当然可以在不中断RxJava调用链的前提下完成这个需求!
你的原始代码问题在于使用flatMapIterable把所有A内部的B对象都摊平成了单独的流元素,这样后续的toList()会把所有过滤后的B混在一起,没法再关联回对应的A对象。我们可以通过两种思路来解决这个问题,全程保持Rx调用链的连贯性:
思路1:直接对每个A对象处理内部B列表(最简洁)
这种方法适合同步过滤B的场景,我们不需要把B拆出A的上下文,而是在map操作符里直接处理每个A的B列表,然后返回更新后的A对象:
class A { int mAId; List<B> mBList; // 推荐添加拷贝构造函数,用于创建带过滤后B列表的新A对象(避免修改原对象带来的副作用) public A(A original, List<B> filteredBList) { this.mAId = original.mAId; this.mBList = filteredBList; } } class B { int mId; } public void processList(List<A> list) { Observable.fromIterable(list) // 对每个A单独处理内部的B列表过滤 .map(originalA -> { // 这里替换成你的实际过滤逻辑,比如过滤mId大于5的B List<B> filteredBs = originalA.mBList.stream() .filter(b -> b.mId > 5) .collect(Collectors.toList()); // 返回更新后的A对象(如果允许修改原对象,也可以直接赋值后返回originalA) return new A(originalA, filteredBs); }) // 可选:把所有处理后的A收集成列表 .toList() .subscribe(processedAList -> { // 这里拿到的就是每个A都带过滤后B列表的结果 System.out.println("处理完成,共" + processedAList.size() + "个A对象"); }, throwable -> { // 处理错误逻辑 throwable.printStackTrace(); }); }
这种方式全程在Rx链中完成,没有中断,逻辑清晰且性能更好,因为不需要拆分再重组元素。
思路2:保留A与B的关联关系(适合异步过滤场景)
如果你的B过滤逻辑是异步操作(比如需要调用网络接口判断是否保留某个B),那可以用flatMap把A和B配对,过滤后再按A分组重组:
public void processListWithAsyncFilter(List<A> list) { Observable.fromIterable(list) // 把每个A和它的B配对,保留关联关系 .flatMap(originalA -> Observable.fromIterable(originalA.mBList) // 这里可以替换成异步过滤逻辑,比如flatMap调用网络接口后判断 .filter(b -> b.mId > 5) // 将A和过滤后的B绑定成键值对 .map(filteredB -> new AbstractMap.SimpleEntry<>(originalA, filteredB)) ) // 按原始A对象分组,收集每个A对应的过滤后B列表 .groupBy(entry -> entry.getKey()) .flatMap(group -> group.map(AbstractMap.SimpleEntry::getValue) .toList() .map(filteredBs -> new A(group.getKey(), filteredBs)) ) .toList() .subscribe(processedAList -> { // 处理结果 }, throwable -> { // 错误处理 }); }
注意事项
- 尽量避免直接修改原A对象的
mBList,创建新的A对象可以保持不可变性,减少多线程环境下的副作用风险。 - 如果是同步过滤,优先用思路1,代码更简洁高效;异步过滤再考虑思路2。
内容的提问来源于stack exchange,提问作者seyed Jafari
相关产品推荐
相关产品推荐

