我可以将Mono<List<Item>>
个数据源列表合并到一个包含所有项目的Mono<List<Item>>
中,而不会阻止吗?
在我的带有Lombok分散 - 收集应用程序的JDK 9 Spring Boot 2中,这个阻止版本有效:
private Mono<List<Item>> gather(List<Mono<List<Item>>> data) {
return Mono.just( data.stream().map(m -> m.block())
.flatMap(List::parallelStream).collect(Collectors.toList()));
}
每个源数据流在其block()
上调用Mono
;如果可能的话,我想减少block()
次呼叫...最好是零。有什么想法吗?
测试用例
@RunWith(SpringRunner.class)
public class ReactiveTests {
@Test
public void testScatterGather() {
List<List<Item>> dataSet = dataSet();
Mono<List<Item>> data = gather(scatter(dataSet));
StepVerifier.create(data)
.expectNext(toItemList(dataSet))
.expectComplete();
}
private Mono<List<Item>> gather(List<Mono<List<Item>>> data) {
return Mono.just( data.stream().map(m -> m.block())
.flatMap(List::parallelStream).collect(Collectors.toList()));
}
private List<Mono<List<Item>>> scatter(List<List<Item>> data) {
return newMonoLists(data);
}
private List<Item> toItemList(List<List<Item>> data) {
return data.stream().flatMap(List::stream).collect(Collectors.toList());
}
private List<Mono<List<Item>>> newMonoLists(List<List<Item>> data) {
return data.stream().map(l -> Mono.just(l)).collect(Collectors.toList());
}
private List<List<Item>> dataSet() {
return Arrays.asList(dataSet(1L),dataSet(4L),dataSet(7L));
}
private List<Item> dataSet(long id) {
return Arrays.asList(new Item(id), new Item(id+1), new Item(id+2));
}
@Data @AllArgsConstructor private static class Item { private Long id; }
}
答案 0 :(得分:1)
假设您有2个具有字符串列表的Mono源。
Mono<List<String>> listMono1 = Mono.just(Arrays.asList("1","3","5","7","9","11"));
Mono<List<String>> listMono2 = Mono.just(Arrays.asList("2","4","6","8","10","12"));
您可以使用方法Flux.merge()合并两个发布商,该方法接收一堆发布商并将它们合并在一起。
但如果您合并下面的发布商,那么它最终会给您List<List<String>>
,这是您不想要的。
Flux.merge(listMono1, listMono2).collectList();
因此,您必须修改listMono1和listMono2,以便它们发出List的各个元素,然后合并它们。为此,您可以使用Mono.flatMapMany()来帮助您从List中发出所有元素。所以,最后你将获得如下组合List:
Flux.merge(listMono1.flatMapMany(Flux::fromIterable),listMono2.flatMapMany(Flux::fromIterable)).collectList();
希望最终得到你想要的东西!