【问题标题】:How to convert List<Mono<T>> to Mono<List<T>>?如何将 List<Mono<T>> 转换为 Mono<List<T>>?
【发布时间】:2019-04-13 08:47:27
【问题描述】:

我有一个返回Mono&lt;Output&gt;的方法:

interface Processor {
  Mono<Output> process(Input input);
}

我想为一个集合执行这个processor 方法:

List<Input> inputs = // get inputs
Processor processor = // get processor
List<Mono<Output>> outputs = inputs.stream().map(supplier::supply).collect(toList());

但我想获得包含汇总结果的Mono&lt;List&lt;Output&gt;&gt;,而不是List&lt;Mono&lt;Output&gt;&gt;

我试过reduce,但最终的结果看起来很笨拙:

Mono<List<Output>> result = inputs.stream().map(processor::process)
    .reduce(Mono.just(new ArrayList<>()),
        (monoListOfOutput, monoOfOutput) ->
            monoListOfOutput.flatMap(list -> monoOfOutput.map(output -> {
              list.add(output);
              return list;
            })),
        (left, right) ->
            left.flatMap(leftList -> right.map(rightList -> {
              leftList.addAll(rightList);
              return leftList;
            })));

我可以用更少的代码实现这一点吗?

【问题讨论】:

  • 你可以用 Mono.just 和使用 map(Mono::block()) 来包装你对“collect(toList)”的调用
  • @manf 然后我会得到Mono&lt;List&lt;Mono&lt;Output&gt;&gt;&gt;。我只需要Mono&lt;List&lt;Output&gt;&gt;。添加了我已经尝试过的方法。
  • @manf 我不想屏蔽。

标签: java project-reactor reactor


【解决方案1】:
// first merge all the `Mono`s:
List<Mono<Output>> outputs = ...
Flux<Output> merged = Flux.empty();
for (Mono<Output> out : outputs) {
    merged = merged.mergeWith(out);
}

// then collect them
return merged.collectList();

或(受亚历山大的回答启发)

Flux.fromIterable(outputs).flatMap(x -> x).collectList();

【讨论】:

    【解决方案2】:

    如果您出于任何原因不必创建流,则可以从输入创建 Flux,映射并收集列表

    Flux.fromIterable(inputs).flatMap(processor::process).collectList();
    

    【讨论】:

    • 即使您确实以outputs 而不是inputs 开头(编辑了我的答案),您也可以使用相同的方法。但这更好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-26
    • 1970-01-01
    • 2019-05-20
    • 2014-02-05
    • 1970-01-01
    相关资源
    最近更新 更多