Как преобразовать список <Mono <T>> в моно <List <T>>? - PullRequest
0 голосов
/ 09 ноября 2018

У меня есть метод, который возвращает Mono<Output>:

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());

Но вместо List<Mono<Output>> я хочу получить Mono<List<Output>>, который будет содержать агрегированные результаты.

Я пытался 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;
            })));

Можно ли добиться этого с меньшим количеством кода?

Ответы [ 2 ]

0 голосов
/ 09 ноября 2018

Если вам не нужно создавать поток по какой-либо причине, вы можете создать Flux из ваших входов, отобразить его и собрать список

Flux.fromIterable(inputs).flatMap(processor::process).collectList();
0 голосов
/ 09 ноября 2018
// 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();
...