概述
本文分享flatMap、flatMapSequential、concatMap之间的区别与联系。
flatMap
源码
public final <R> Flux<R> flatMap(Function<? super T, ? extends Publisher<? extends R>> mapper) {
return flatMap(mapper, Queues.SMALL_BUFFER_SIZE, Queues
.XS_BUFFER_SIZE);
}
jdk注释
Transform the elements emitted by this Flux asynchronously into Publishers, then flatten these inner publishers into a single Flux through merging, which allow them to interleave.
There are three dimensions to this operator that can be compared with flatMapSequential and concatMap:
Generation of inners and subscription: this operator is eagerly subscribing to its inners.
Ordering of the flattened values: this operator does not necessarily preserve original ordering, as inner element are flattened as they arrive.
Interleaving: this operator lets values from different inners interleave (similar to merging the inner sequences).
翻译
把Flux弹出的元素异步的转化成发布者(Publishers),然后把他们合并成一个Flux。在合并的过程中允许交错(不保证顺序)
可以从三个方面比较flatMap与flatMapSequential和concatMap的区别:
生成内部发布者与订阅关系:flatMap并发的订阅了它的内部发布者。
合并顺序:flatMap按照内部内部订阅到达顺序合并元素,它不保证与原始顺序一致。
交错:flatMap允许不同的内部订阅交错(与merge类似)
图示
flatMapSequential
源码
public final <R> Flux<R> flatMapSequential(Function<? super T, ? extends
Publisher<? extends R>> mapper) {
return flatMapSequential(mapper, Queues.SMALL_BUFFER_SIZE);
}
jdk注释
Transform the elements emitted by this Flux asynchronously into Publishers, then flatten these inner publishers into a single Flux, but merge them in the order of their source element.
There are three dimensions to this operator that can be compared with flatMap and concatMap:
Generation of inners and subscription: this operator is eagerly subscribing to its inners (like flatMap).
Ordering of the flattened values: this operator queues elements from late inners until all elements from earlier inners have been emitted, thus emitting inner sequences as a whole, in an order that matches their source's order.
Interleaving: this operator does not let values from different inners interleave (similar looking result to concatMap, but due to queueing of values that would have been interleaved otherwise).
翻译
把Flux弹出的元素异步的转化成发布者(Publishers),然后按照源头发出元素的顺序把他们合并成一个Flux。
可以从三个方面比较flatMapSequential与flatMap和concatMap的区别:
生成内部发布者与订阅关系:像flatMap一样,flatMapSequential并发的订阅了它的内部发布者。
合并顺序:flatMapSequential把所有的内部订阅排序,直到所有的订阅都完成,然后把所有的序列按照原始的顺序一起发出去。
交错:flatMapSequential不允许内部订阅相互交错(与concatMap的结果类似,flatMapSequential使用队列防止交错)
图示
concatMap
源码
public final <V> Flux<V> concatMap(Function<? super T, ? extends Publisher<? extends V>>
mapper) {
return concatMap(mapper, Queues.XS_BUFFER_SIZE);
}
jdk注释
Transform the elements emitted by this Flux asynchronously into Publishers, then flatten these inner publishers into a single Flux, sequentially and preserving order using concatenation.
There are three dimensions to this operator that can be compared with flatMap and flatMapSequential:
Generation of inners and subscription: this operator waits for one inner to complete before generating the next one and subscribing to it.
Ordering of the flattened values: this operator naturally preserves the same order as the source elements, concatenating the inners from each source element sequentially.
Interleaving: this operator does not let values from different inners interleave (concatenation).
翻译
把Flux弹出的元素异步的转化成发布者(Publishers),然后使用级联的方式,依照顺序依次把这些内部的publishers压平成一个Flux。
可以从三个方面比较concatMap与flatMap与flatMapSequential的区别:
生成内部发布者与订阅关系:concatMap等待一个内部订阅完成之后,在生成和订阅下一个。
压平顺序:concatMap保证拍平的顺序与源头发出元素的顺序一致,它依次把内部订阅级联起来。
交错:concatMap不允许内部订阅相互交错
图示
代码测试
public static void main(String[] args) throws Exception{
List<Integer> list = new ArrayList<>();
list.add(4);
list.add(2);
list.add(1);
list.add(3);
Flux.fromIterable(list).flatMap(item ->{
return Mono.just(item).delayElement(Duration.ofMillis(item * 100));
}).doOnSubscribe(subscribe ->{
System.out.print("flatmap : ");
}).doOnComplete(()->{
System.out.println();
}).subscribe(result ->{
System.out.print(result + " ");
});
Thread.sleep(1100);
Flux.fromIterable(list).flatMapSequential(item ->{
return Mono.just(item).delayElement(Duration.ofMillis(item * 100));
}).doOnSubscribe(subscription -> {
System.out.print("flatMapSequential : ");
}).doOnComplete(()->{
System.out.println();
}).subscribe(result ->{
System.out.print(result + " ");
});
Thread.sleep(1100);
Flux.fromIterable(list).concatMap(item ->{
return Mono.just(item).delayElement(Duration.ofMillis(item * 100));
}).doOnSubscribe(subscription -> {
System.out.print("concatMap : ");
}).doOnComplete(()->{
System.out.println();
}).subscribe(result ->{
System.out.print(result + " ");
});
Thread.sleep(1100);
}
输出
总结
相同点
1. 接口声明是一样的,都是把元素T转换成Publisher
不同点
1. flatMap不保证顺序, flatMapSequential和concatMap保持顺序。
2. flatMapSequential效率高,它是并发的,concatMap是串行方式。