RXJava2 | Android:过滤arrayList并跟踪过滤器

RXJava2 | Android:过滤arrayList并跟踪过滤器

问题描述:

场景:RXJava 2. Android。RXJava2 | Android:过滤arrayList并跟踪过滤器

想象一下,你有从迭代可观察到的,像这样:Observable.fromIterable(arrayList<Something>),你需要做两件事情吧:

  1. 筛选的项目。

  2. 知道一个项目是否被过滤出来(又名:过滤函数返回false至少一次)。

这是一个类似观察到的(极度简化是相关的):

final ArrayList<Something> someArrayList = getTheArrayList(); 

    Observable 
      .fromIterable(someArrayList) 
      .subscribeOn(Schedulers.computation()) 
      .filter(new AppendOnlyLinkedArrayList.NonThrowingPredicate<Something>() { 
       @Override 
       public boolean test(final Something something) { 
        return something.isValid(); 
       } 
      }) 
      .toList() 
      .observeOn(AndroidSchedulers.mainThread()) 
      .doOnSuccess(new Consumer<List<Something>>() { 
       @Override 
       public void accept(@NonNull final List<Something> somethings) 
        throws Exception { 
         // How can I tell if the filter above returned false 
         // at least once? 
       } 
      }) 
      .subscribe(); 

为了回答上述问题,一种选择是将原始someArrayList比较somethings。如果它们不同,那么发生了一些事情。但是这意味着列表必须以相同的顺序具有相同的项目,如果Something是一个复杂的对象,必须实现一个equals,这可能会成为问题。

B计划,这是我现在用的,我不喜欢的是保持一个“布尔阵”外观察到,像这样:

final boolean[] hasInvalidData = new boolean[1];

,然后在.filter我可以做:

final isValid = something.isValid(); 
    if (!isValid) { 
     hasInvalidData[0] = true; 
    } 
    return isValid; 

和成功,我可以简单地这样做:

if (hasInvalidData[0]) { 
     // Something has been filtered 
    } 

问题是:有没有更好的方法?

UPDATE

我迄今所做的仅仅是比较originalList.size()finalEmitedList.size()。如果它们不同,那意味着我的过滤器“过滤”了一些东西。

我读它的方式,闻起来像是XY problem。如果您需要跟踪的元素,你只需要计算,直到找到一个元素,一切都变得容易得多:

Observable 
.fromIterable(someArrayList) 
.subscribeOn(Schedulers.computation()) 
.map(something -> something.isValid()) 
.filter(bool -> bool) 
.first(false); 

如果你确实需要的元素列表:

Observable<Something> source = Observable 
    .fromIterable(someArrayList) 
    .subscribeOn(Schedulers.computation()) 
    .publish() 
    .autoConnect(2); 

source 
.map(something -> something.isValid()) 
.reduce(false, (a,b) -> a | b) 
.zipWith(source.toList(), (flag, list) -> { 
    // do your stuff 
}) 
.subscribe(); 
+0

它可以是一个XY问题(我意识到这一点,感谢您刷新我的记忆),但是...我需要跟踪列表(最后,也就是过滤后)。我只需要知道一个项目是否被过滤(任何)。我所做的基本上是,计算最后的项目数量并比较它们是否相同。由于唯一的操作是删除(过滤器),最终列表将包含更少项目的唯一方法是过滤器返回false。比布尔事件好得多,但也许有更好的办法。 –

+0

也许你想将所有'Something's转换为'Pair '。 –

+0

请注意,由于您没有flatMap或类似地图,因此您将按顺序计算所有内容。 –

不知道它的工作原理,但Observable.sequenceEqual可以工作:

ArrayList<Object> list = ... 
Predicate myFilter = ... 
Observable<Object> observable = Observable.fromIterable(list); 
Observable.sequenceEqual(observable, observable.filter(myFilter)) 
    .subscribe(new Consumer<Boolean>() { 
     @Override 
     public void accept(@NonNull Boolean changed) throws Exception { 
      // result here 
     } 
    });