Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/346.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
RxJava:如何组合多个具有依赖性的观测值,并在最后收集所有结果?_Java_Functional Programming_Reactive Programming_Rx Java - Fatal编程技术网

RxJava:如何组合多个具有依赖性的观测值,并在最后收集所有结果?

RxJava:如何组合多个具有依赖性的观测值,并在最后收集所有结果?,java,functional-programming,reactive-programming,rx-java,Java,Functional Programming,Reactive Programming,Rx Java,我正在学习RxJava,作为我的第一个实验,我尝试在中的第一个run()方法中重写代码(引用为RxJava可以帮助解决的问题),以使用RxJava改进其异步性,也就是说,这样它就不用等到第一个未来的结果(f1.get())之后再继续编写其余的代码 f3取决于f1。我明白了如何处理这个问题,flatMap似乎做到了这一点: Observable<String> f3Observable = Observable.from(executor.submit(new CallToRemote

我正在学习RxJava,作为我的第一个实验,我尝试在中的第一个
run()
方法中重写代码(引用为RxJava可以帮助解决的问题),以使用RxJava改进其异步性,也就是说,这样它就不用等到第一个未来的结果(
f1.get()
)之后再继续编写其余的代码

f3
取决于
f1
。我明白了如何处理这个问题,
flatMap
似乎做到了这一点:

Observable<String> f3Observable = Observable.from(executor.submit(new CallToRemoteServiceA()))
    .flatMap(new Func1<String, Observable<String>>() {
        @Override
        public Observable<String> call(String s) {
            return Observable.from(executor.submit(new CallToRemoteServiceC(s)));
        }
    });
这开始变得很奇怪(
merge
ing它们可能不是我想要的…),但最终允许我这样做,而不是我想要的:

f3Observable.subscribe(new Action1<String>() {
    @Override
    public void call(String s) {
        System.out.println("Observed from f3: " + s);
        f4And5Observable.subscribe(new Action1<Integer>() {
            @Override
            public void call(Integer i) {
                System.out.println("Observed from f4 and f5: " + i);
            }
        });
    }
});
这是所有的数字,但不幸的是,我在单独的调用中得到了结果,所以我不能完全替换原始代码中的最终println:

System.out.println(f3.get() + " => " + (f4.get() * f5.get()));

我不明白如何在同一行中访问这两个返回值。我想这里可能缺少一些函数式编程。我该怎么做?谢谢。

看来你真正需要的是更多的鼓励和对如何使用RX的看法。我建议您阅读更多的文档以及大理石图(我知道它们并不总是有用的)。我还建议查看
lift()
函数和操作符

  • 一个可观察对象的全部要点是将数据流和数据操作连接到一个对象中
  • 调用
    map
    flatMap
    filter
    的要点是操作数据流中的数据
  • 合并的重点是合并数据流
  • 运算符的作用是允许您中断稳定的可观测数据流,并定义您自己对数据流的操作。例如,我编写了一个移动平均运算符。它将可观察到的双倍中的双倍相加,以返回移动平均值流。代码看起来就像这样

    Observable movingAverage=Observable.from(mDoublesArray.lift)(新的MovingAverageOperator(frameSize))

很多你认为理所当然的过滤方法都有
lift()
,这让你松了一口气

话虽如此,;合并多个依赖项所需的全部工作是:

  • 使用
    map
    flatMap
  • 将标准数据类型合并到流
  • 如果一个对象需要等待另一个对象,或者需要在流中排序数据,则使用自定义运算符。警告:此方法将减慢流速度
  • 用于列出或订阅以收集所有这些数据

<强>编辑:< /强>某人把下面的文本转换成一个答案,我把它作为一个编辑来回答,我很欣赏,理解可能是正确的事情,但是我不认为这是一个答案,因为它显然不是正确的方法。我不会使用此代码,也不会建议任何人复制它欢迎其他/更好的解决方案和评论


我能够用以下方法解决这个问题。我没有意识到你可以不止一次地观察一个可观察的东西,我假设结果只能被消耗一次。因此,我只需两次观察到
flatMap
f2Observable(对不起,我在我最初的帖子中重命名了代码中的一些内容),然后在所有观察到的内容上使用
zip
,然后订阅它。在
zip
中使用
Map
来聚合值是不可取的,因为类型会发生变化欢迎其他/更好的解决方案和评论最新版本。多谢各位

Future<Integer> f2 = executor.submit(new CallToRemoteServiceB());
Observable<Integer> f2Observable = Observable.from(f2);
Observable<Integer> f4Observable = f2Observable
    .flatMap(new Func1<Integer, Observable<Integer>>() {
        @Override
        public Observable<Integer> call(Integer integer) {
            System.out.println("Observed from f2: " + integer);
            Future<Integer> f4 = executor.submit(new CallToRemoteServiceD(integer));
            return Observable.from(f4);
        }       
    });     

Observable<Integer> f5Observable = f2Observable
    .flatMap(new Func1<Integer, Observable<Integer>>() {
        @Override
        public Observable<Integer> call(Integer integer) {
            System.out.println("Observed from f2: " + integer);
            Future<Integer> f5 = executor.submit(new CallToRemoteServiceE(integer));
            return Observable.from(f5);
        }       
    });     

Observable.zip(f3Observable, f4Observable, f5Observable, new Func3<String, Integer, Integer, Map<String, String>>() {
    @Override
    public Map<String, String> call(String s, Integer integer, Integer integer2) {
        Map<String, String> map = new HashMap<String, String>();
        map.put("f3", s);
        map.put("f4", String.valueOf(integer));
        map.put("f5", String.valueOf(integer2));
        return map;
    }       
}).subscribe(new Action1<Map<String, String>>() {
    @Override
    public void call(Map<String, String> map) {
        System.out.println(map.get("f3") + " => " + (Integer.valueOf(map.get("f4")) * Integer.valueOf(map.get("f5"))));
    }       
});     

我想你要找的是开关地图。我们遇到了一个类似的问题,我们有一个会话服务来处理从api获取新会话,我们需要该会话才能获取更多数据。我们可以将sessionobservate添加到返回sessionToken的sessionobservate中,以便在数据调用中使用

getSession返回一个可观察的

public getSession(): Observable<any>{
  if (this.sessionToken)
    return Observable.of(this.sessionToken);
  else if(this.sessionObservable)
    return this.sessionObservable;
  else {
    // simulate http call 
    this.sessionObservable = Observable.of(this.sessonTokenResponse)
    .map(res => {
      this.sessionObservable = null;
      return res.headers["X-Session-Token"];
    })
    .delay(500)
    .share();
    return this.sessionObservable;
  }
}
您仍然需要一个平面图来组合非相关的观测值

普朗克:


我是在哪里想到使用开关映射的:

您想要
toList
?非常感谢您的回复。我希望不久有一天能重新使用RxJava。我从你那里学到了这项技术!它工作得很好,但我想知道是否有一种“更干净”的方法来处理这种常见的情况。我有两个可观察到的相互依赖,可观察到的2依赖于可观察到的1,所以可观察到的1应该在可观察到的2之前执行,然后我需要结合两个可观察到的结果。我们有接线员吗。我能做这项工作。我不想使用flatMap,因为它将一个流转换为另一个流,但这里我需要设置依赖项,然后压缩结果。请回复。嗨,谢谢你的回答!我已经很久没有看RxJava了,我真的不知道我是否应该把它作为公认的答案。但肯定是投票率上升了。
Future<Integer> f2 = executor.submit(new CallToRemoteServiceB());
Observable<Integer> f2Observable = Observable.from(f2);
Observable<Integer> f4Observable = f2Observable
    .flatMap(new Func1<Integer, Observable<Integer>>() {
        @Override
        public Observable<Integer> call(Integer integer) {
            System.out.println("Observed from f2: " + integer);
            Future<Integer> f4 = executor.submit(new CallToRemoteServiceD(integer));
            return Observable.from(f4);
        }       
    });     

Observable<Integer> f5Observable = f2Observable
    .flatMap(new Func1<Integer, Observable<Integer>>() {
        @Override
        public Observable<Integer> call(Integer integer) {
            System.out.println("Observed from f2: " + integer);
            Future<Integer> f5 = executor.submit(new CallToRemoteServiceE(integer));
            return Observable.from(f5);
        }       
    });     

Observable.zip(f3Observable, f4Observable, f5Observable, new Func3<String, Integer, Integer, Map<String, String>>() {
    @Override
    public Map<String, String> call(String s, Integer integer, Integer integer2) {
        Map<String, String> map = new HashMap<String, String>();
        map.put("f3", s);
        map.put("f4", String.valueOf(integer));
        map.put("f5", String.valueOf(integer2));
        return map;
    }       
}).subscribe(new Action1<Map<String, String>>() {
    @Override
    public void call(Map<String, String> map) {
        System.out.println(map.get("f3") + " => " + (Integer.valueOf(map.get("f4")) * Integer.valueOf(map.get("f5"))));
    }       
});     
responseB_responseA => 714000
public getSession(): Observable<any>{
  if (this.sessionToken)
    return Observable.of(this.sessionToken);
  else if(this.sessionObservable)
    return this.sessionObservable;
  else {
    // simulate http call 
    this.sessionObservable = Observable.of(this.sessonTokenResponse)
    .map(res => {
      this.sessionObservable = null;
      return res.headers["X-Session-Token"];
    })
    .delay(500)
    .share();
    return this.sessionObservable;
  }
}
public getData() {
  if (this.dataObservable)
    return this.dataObservable;
  else {
    this.dataObservable = this.sessionService.getSession()
      .switchMap((sessionToken:string, index:number) =>{
        //simulate data http call that needed sessionToken
          return Observable.of(this.dataResponse)
          .map(res => {
            this.dataObservable = null;
            return res.body;
          })
          .delay(1200)
        })
        .map ( data => {
          return data;
        })
        .catch(err => {
          console.log("err in data service", err);
         // return err;
        })
        .share();
    return this.dataObservable;
  }
}