RxJava2 filter List<Object>

2019-04-26 13:49发布

I'm trying to filter a List with RxJava2 such that each item (object) in the list should pass a validation check and I get a resulting List with only items that pass that test. For instance if my Object had the following structure,

class MyClassA {
    int value1;
    int value2;
}

I want to only get the list of items where the value2 is 10.

I have an API call function that returns an Observable of List, i.e. Observable<List<MyClassA>> as follows,

apiService.getListObservable()
    .subscribeOn(Schedulers.io)
    .observeOn(AndroidSchedulers.mainThread());

and I would like to have the output filtered, so I tried adding a .filter() operator to the above but it seems to require a Predicate<List<MyClassA>> instead of just a MyClassA object with which I can check and allow only ones where value2 == 10.

I'm pretty new to RxJava and RxJava2 and seems like I'm missing something basic here?

TIA

2条回答
Root(大扎)
2楼-- · 2019-04-26 14:26

You can unroll the list and then collect up those entries that passed the filter:

apiService.getListObservable()
.subscribeOn(Schedulers.io)
.flatMapIterable(new Function<List<MyClassA>, List<MyClassA>>() {
    @Override public List<MyClassA> apply(List<MyClassA> v) {
        return v;
    }
})
.filter(new Predicate<MyClassA>() {
    @Override public boolean test(MyClassA v) {
        return v.value2 == 10;
    }
})
.toList()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(...);
查看更多
闹够了就滚
3楼-- · 2019-04-26 14:27

You may take a look at the below. It demonstrates the ways to print just the filtered objects OR the lists that contain filtered objects. Here the filtering logic is to retain the org.apache.commons.lang3.tuple.Pairs that have even numbers in right.

public static void main(String[] args) {
    // print raw output
    getListObservable().subscribe(System.out::println);

    // print the objects post filtering
    getListObservable().flatMap(v -> Observable.from(v)).filter(p -> p.getRight()%2==0).subscribe(System.out::println);

    // print the list refined with only filtered objects
    getListObservable().flatMap(v -> Observable.just(v.stream().filter(p -> p.getRight()%2==0).collect(Collectors.toList()))).subscribe(System.out::println);

}

private static Observable<List<Pair<Integer, Integer>>> getListObservable() {
    return Observable.create(subscriber -> {
        for(int i=0; i<5; i++){
            List<Pair<Integer, Integer>> list = new ArrayList<>();
            for(int j=0; j<5; j++){
                list.add(Pair.of(i, j));
            }
            subscriber.onNext(list);
        }
    });

}

Output with contents of observable:

[(0,0), (0,1), (0,2), (0,3), (0,4)]
[(1,0), (1,1), (1,2), (1,3), (1,4)]
[(2,0), (2,1), (2,2), (2,3), (2,4)]
[(3,0), (3,1), (3,2), (3,3), (3,4)]
[(4,0), (4,1), (4,2), (4,3), (4,4)]

Output to contain only filtered objects:

(0,0)
(0,2)
(0,4)
(1,0)
(1,2)
(1,4)
(2,0)
(2,2)
(2,4)
(3,0)
(3,2)
(3,4)
(4,0)
(4,2)
(4,4)

Output to contain the lists that contain only filtered objects.

[(0,0), (0,2), (0,4)]
[(1,0), (1,2), (1,4)]
[(2,0), (2,2), (2,4)]
[(3,0), (3,2), (3,4)]
[(4,0), (4,2), (4,4)]
查看更多
登录 后发表回答