java - 惰性组合 Observables

标签 java functional-programming rx-java reactive-programming

说我有这个

Observable<A> getA() {
  return Observable.just(new A());
}

Observable<C> getC() {
  // ... some expensive call
  return Observable.just(new C());
}

Observable<B> getB() {
  return getA()
    .map(a -> {
      if (a.someCondition()) {
        final B b = new B();
        b.setSomeFields(...);
        return b;
      }
      if (a.otherCondition()) {
        final B b = new B();
        b.setOtherFields(...);
        return b;
      }
      final B b = new B(...);
      b.setC(getC().toBlocking().single());
      return b;
    });
}

其中 getC() 执行一些昂贵的调用(或有副作用)。我只想在 a.someCondition()a 时进行此调用并初始化 B.c 字段。如上所述,不满足 otherCondition()

我该如何重写以摆脱 .toBlocking()

我想到的一种方法是压缩 getA()getC():

Observable<B> getB() {
  return Observable.zip(getA(), getC(), (a, c) -> Tuple.of(a, c))
    .map(tuple -> {
      final A a = tuple._1;
      final C c = tuple._2;
      if (a.someCondition()) {
        final B b = new B();
        b.setSomeFields(...);
        return b;
      }
      if (a.otherCondition()) {
        final B b = new B();
        b.setOtherFields(...);
        return b;
      }
      final B b = new B(...);
      b.setC(c);
      return b;
    });
}

但这会一直造成昂贵的调用。当有更复杂的条件或当我有超过 2 个 Observables 需要压缩时,也使得阅读变得困难。

编辑:

@ESala 下面的答案有效,但有时从 map 切换到 flatMap 需要进行大量更改。下面的解决方案也有效吗?

Observable<B> getB() {
  return getA()
    .map(a -> {
      if (a.someCondition()) {
        final B b = new B();
        b.setSomeFields(...);
        return b;
      }
      if (a.otherCondition()) {
        final B b = new B();
        b.setOtherFields(...);
        return b;
      }
      final B b = new B(...);
      getC().forEach(c -> b.setC(c));
      return b;
    });
}

最佳答案

您可以使用flatMap而不是map ,这样你就可以避免 toBlocking并且只有在必要时才会进行昂贵的调用。

示例:

Observable<B> getB() {
  return getA()
    .flatMap(a -> {                  // <-- flatMap here
      if (a.someCondition()) {
        final B b = new B();
        b.setSomeFields(...);
        return Observable.just(b);   // <-- wrap in observable
      }
      if (a.otherCondition()) {
        final B b = new B();
        b.setOtherFields(...);
        return Observable.just(b);   // <-- wrap in observable
      }
      return getC().map(c -> {       // <-- expensive call executed
          B b = new B(...);          //     only when necessary
          b.setC(c);
          return b;
      });
    });
}
<小时/>

关于问题中的编辑的更新:

我不认为切换到 flatMap需要做很多改变。有具体例子吗?

关于您编辑中的替代解决方案:它可以在这种情况下工作,但我不推荐它。

通过这样做,您将创建另一个订阅,该订阅不由主要可观察流管理,通常这种情况不应该发生。 forEach运算符返回 Disposable它悬在那里!

它可能导致的一些问题包括:1)如果您取消订阅主要可观察量,forEach无论如何,订阅都会继续,2) 如果您在 getC() 中指定了调度程序方法,主要可观察量可以在 forEach 之前完成已经完成了。

关于java - 惰性组合 Observables,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47419576/

相关文章:

java - 如何获取 Spring Restful Web 服务中请求正文中发送的字符串?

java - 创建 Firefox 配置文件并关闭木偶

java - Servlet 加载图片/jpg 不起作用

rx-java - 为什么RxJava中没有 `Single#doOnTerminate`方法?

rx-java - 链接具有不同发射类型的多个可观察量

java - 如何在 Java 中将 RegEx 表达式作为参数传递?

haskell - Haskell 中的内存

Java - 函数式浮点计算

node.js - 用于 CSV 解析的 Highland.js

java - RxJava 中的笛卡尔积