【问题标题】:Split a flux into two fluxes - head and tail将助焊剂分成两个助焊剂 - 头部和尾部
【发布时间】:2020-02-29 23:20:24
【问题描述】:

我想将通量分成两个通量,其中第一个具有原始通量的第一项,第二个将获取其余项。

在对每个通量应用自定义转换 myLogic 后,我想将它们组合成一个通量,保留原始通量的顺序。

例子:

S:学生
S':申请后的学生myLogic

发射通量:s1 -> s2 -> s3 -> s4
第一个分裂通量:s1' => myLogic
第二次分裂通量:s2' -> s3' -> s4' => myLogic
合流:s1' -> s2' -> s3' -> s4'

【问题讨论】:

  • 也许你只需要一个LinkedList
  • @suliman 请接受您认为对该问题最有帮助的答案。

标签: java spring-boot spring-webflux project-reactor


【解决方案1】:

使用标准的Flux 方法takeskip 来分离头部和尾部元素就足够了。在此之前调用cache 也有助于避免重复订阅。

class Util {

  static <T, V> Flux<V> dualTransform(
    Flux<T> originalFlux,
    int cutpointIndex,
    Function<T, V> transformHead,
    Function<T, V> transformTail
  ) {
    var cached = originalFlux.cache();
    var head = cached.take(cutpointIndex).map(transformHead);
    var tail = cached.skip(cutpointIndex).map(transformTail);

    return Flux.concat(head, tail);
  }

  static void test() {
    var sample = Flux.just("a", "b", "c", "d");

    var result = dualTransform(
                   sample,
                   1, 
                   x -> "{" + x.toUpperCase() + "}", 
                   x -> "(" + x + ")"
                 );

    result.doOnNext(System.out::print).subscribe();

    // prints: {A}(b)(c)(d)
  }
}

【讨论】:

    【解决方案2】:

    您的问题有一个更简单的解决方案。您不需要拆分和合并来自发布者的事件。您可以使用index()。它保存有关事件发布顺序的信息。

    Flux<String> values = Flux.just("s1", "s2", "s3");
    values.index((i, v) -> {
      if (i == 0) {
        return v.toUpperCase();
      } else {
        return v.toLowerCase();
      }
    });
    

    【讨论】:

      【解决方案3】:

      这里有一个 hacky 方法来做到这一点:

      boolean a[] = new boolean[]{false};  //use an array as you cannot use non-final variables inside lambdas
      
          originalFlux
              .flatMap(a -> {
                  if(!a[0]) {
                      a[0] = true;
                      return runLogicForFirst(a);
                  } else {
                      return runLogicForRest(a);
                  }
              })
      

      【讨论】:

        【解决方案4】:

        无需创建两个单独的 Flux 对象然后合并它们,您只需将原始 Flux 与另一个 Flux&lt;Boolean&gt; 压缩,后者仅在第一个元素上使用 true

        然后,您可以在正常的map() 电话中随意进行有条件的处理,而无需稍后合并单独的发布者:

        Flux<String> values = Flux.just("A", "B", "C", "D", "E", "F", "G");
        
        Flux.zip(Flux.concat(Flux.just(true), Flux.just(false).repeat()), values)
                .map(x -> x.getT1() ? "_"+x.getT2().toUpperCase()+"_" : x.getT2().toLowerCase())
                .subscribe(System.out::print);    // prints "_A_bcdefg"
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-02-11
          • 1970-01-01
          • 2015-03-22
          • 1970-01-01
          • 2016-03-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多