2017-05-26 89 views
1

場景: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()。如果它們不同,那意味着我的過濾器「過濾」了一些東西。

回答

2

我讀它的方式,聞起來像是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或類似地圖,因此您將按順序計算所有內容。 –

1

不知道它的工作原理,但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 
     } 
    });