Как преобразовать List<Mono> в Mono><Список>?

#spring-boot #spring-webflux

#Ява #проект-реактор #реактор

Вопрос:

У меня есть метод, который возвращает Monolt;Outputgt; :

 interface Processor {  Monolt;Outputgt; process(Input input); }  

И я хочу выполнить этот processor метод для коллекции:

 Listlt;Inputgt; inputs = // get inputs Processor processor = // get processor Listlt;Monolt;Outputgt;gt; outputs = inputs.stream().map(supplier::supply).collect(toList());  

Но вместо a Listlt;Monolt;Outputgt;gt; я хочу получить Monolt;Listlt;Outputgt;gt; то, что будет содержать агрегированные результаты.

Я пытался reduce , но конечный результат выглядит очень неуклюжим:

 Monolt;Listlt;Outputgt;gt; result = inputs.stream().map(processor::process)  .reduce(Mono.just(new ArrayListlt;gt;()),  (monoListOfOutput, monoOfOutput) -gt;  monoListOfOutput.flatMap(list -gt; monoOfOutput.map(output -gt; {  list.add(output);  return list;  })),  (left, right) -gt;  left.flatMap(leftList -gt; right.map(rightList -gt; {  leftList.addAll(rightList);  return leftList;  })));  

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

Комментарии:

1. Вы могли бы просто обернуть свой вызов «собрать(список)» с помощью Mono.just и использовать карту(Mono::block())

2. @manf Тогда я получу Monolt;Listlt;Monolt;Outputgt;gt;gt; . Мне нужно просто Monolt;Listlt;Outputgt;gt; вместо этого. Добавлен подход, который я уже пробовал.

3. @manf Я не хочу блокировать.

Ответ №1:

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

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

Комментарии:

1. Вы можете использовать тот же подход, даже если начнете с outputs вместо inputs (отредактировал мой ответ). Но так будет лучше.

Ответ №2:

 // first merge all the `Mono`s: Listlt;Monolt;Outputgt;gt; outputs = ... Fluxlt;Outputgt; merged = Flux.empty(); for (Monolt;Outputgt; out : outputs) {  merged = merged.mergeWith(out); }  // then collect them return merged.collectList();  

или (вдохновленный ответом Александра)

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