RxJava比较两个observable中的不同项(java 7)

时间:2017-04-10 16:06:26

标签: java rx-java contains

我有两个Observables ob1&发出物品的ob2。如果ob1.item包含在ob2中,我想忽略它。

示例:

ob1 contains A,B,C,D

ob2 contains E,C,B,G,J,O

输出:

ob contains A,D

表达此信息的最佳方式是什么?

2 个答案:

答案 0 :(得分:9)

contains运算符返回Observable<Boolean>,以确定observable是否包含给定元素。

Observable<Boolean> contains = observable2.contains(string);

您需要的是将observable1中的所有元素映射到那些布尔可观察量

observable1.map(new Func1<String, Observable<Boolean>>() {
    @Override
    public Observable<Boolean> call(final String string) {
        return observable2.contains(string);
    }
})

这会给你Observable<Observable<Boolean>>,但是很难解决这个问题。因此,您将所有这些布尔可观察量连接成一个。 Luckilly,您需要做的就是使用concatMap代替map

observable1.concatMap(new Func1<String, Observable<Boolean>>() {
    @Override
    public Observable<Boolean> call(final String string) {
        return observable2.contains(string);
    }
})

现在您有一个observable1包含您的元素,Observable<Boolean>包含一个布尔值,表示observable1中的元素是否包含在observable2

observable1:            A ---- B ---- C ---- D
concatMapObservable:    false  true   true   false

您可以轻松zip将这两个observable转换为一个observable,它将传递observable2中未包含的元素,并用空字符串替换其他元素

[concatMapObservable].zipWith(observable1, new Func2<Boolean, String, String>() {
    @Override
    public String call(final Boolean contains, final String string) {
        return contains ? "" : string;
    }
}

然后你过滤空字符串

[zippedObservable].filter(new Func1<String, Boolean>() {
    @Override
    public Boolean call(final String string) {
        return !TextUtils.isEmpty(string);
    }
})

整个代码放在一起:

Observable<String> observable1 = Observable.from(new String[]{"A", "B", "C", "D"});
Observable<String> observable2 = Observable.from(new String[]{"E", "C", "B", "G", "J", "O"});

observable1.concatMap(new Func1<String, Observable<Boolean>>() {
    @Override
    public Observable<Boolean> call(final String string) {
        return observable2.contains(string);
    }
}).zipWith(observable1, new Func2<Boolean, String, String>() {
    @Override
    public String call(final Boolean contains, final String string) {
        return contains ? "" : string;
    }
}).filter(new Func1<String, Boolean>() {
    @Override
    public Boolean call(final String string) {
        return !TextUtils.isEmpty(string);
    }
}).subscribe(new Action1<String>() {
    @Override
    public void call(final String string) {
        Log.d("observable:", string);
    }
});

答案 1 :(得分:3)

在收到ob2的所有项目之前,无法计算操作的输出,因为在知道所有属于ob2的项目之前,无法确定ob1中的项目是否包含在ob2中。因此,您必须等待ob2完成,然后才能从ob1过滤项目。

使用RxJava2的可能解决方案如下。

    Observable<String> ob1 = Observable.fromArray("A", "B", "C", "D");
    Observable<String> ob2 = Observable.fromArray("E", "C", "B", "G", "J", "O");

    Observable.combineLatest(ob2.toList().toObservable(), ob1, (list, value) -> list.contains(value) ? "" : value)
            .filter(value -> !TextUtils.isEmpty(value))
            .subscribeOn(Schedulers.computation())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(value -> Log.d("foo", "Value: " + value));