kotlin : flatMap 与 rxJava flatMap 对比

先看一段代码:


    val strings = listOf("abc", "de")
    strings.map { s -> s.toList() }
    strings.flatMap { s -> s.toSet() }.run { println("flatMap: $this") }
    // flatMap: [a, b, c, d, e]

    strings.map { s -> s.toSet() }.run { println("map: $this") }
    // map: [[a, b, c], [d, e]]
    strings.map { s -> s.toSet() }.flatten().run { println("map + flatten : $this") }

看输出:

flatMap: [a, b, c, d, e]
map: [[a, b, c], [d, e]]
map + flatten : [a, b, c, d, e]

看源码:

public inline fun  Iterable.map(transform: (T) -> R): List {
    return mapTo(ArrayList(collectionSizeOrDefault(10)), transform)
}
public inline fun > Iterable
						.mapTo(destination: C, transform: (T) -> R): C {
    for (item in this)
        destination.add(transform(item))
    return destination
    
}

// =================
public inline fun  Iterable.flatMap(transform: (T) -> Iterable): List {
    return flatMapTo(ArrayList(), transform)
}

public inline fun > Iterable
			.flatMapTo(destination: C, transform: (T) -> Iterable): C {
    for (element in this) {
        val list = transform(element)
        destination.addAll(list)
    }
    return destination
}

对比 map 与 flatMap 发现区别在于一个是调用 add() , 一个是调用 addAll().

这就明白了,为什么上面的输出 flatMap 之后是一个集合,每个元素是原始数据;而 map 之后,每个元素是一个集合。

其实 kt 的 map 与 flatMap 是对集合的操作,而 rxJava2 中是对 Flowable 进行操作的。
也就是二者其实并没有什么对比性。但是由于函数名相同容易让人混淆。

看一下 rxJava 的 map 与 FlatMap 源码

    public final  Flowable map(Function mapper) {
        ObjectHelper.requireNonNull(mapper, "mapper is null");
        return RxJavaPlugins.onAssembly(new FlowableMap(this, mapper));
    }

    public final  Flowable flatMap(Function> mapper,
            boolean delayErrors, int maxConcurrency, int bufferSize) {
        ObjectHelper.requireNonNull(mapper, "mapper is null");
        ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency");
        ObjectHelper.verifyPositive(bufferSize, "bufferSize");
        if (this instanceof ScalarCallable) {
            @SuppressWarnings("unchecked")
            T v = ((ScalarCallable)this).call();
            if (v == null) {
                return empty();
            }
            return FlowableScalarXMap.scalarXMap(v, mapper);
        }
        return RxJavaPlugins.onAssembly(new FlowableFlatMap(this, mapper, delayErrors, maxConcurrency, bufferSize));
    }

主要看Function的第二个参数的类型,对于 map 操作,第二个参数类型是? extends R;而 flatMap 的第二个参数的类型是? extends Publisher>

Flowable 是 Publisher 接口的一个实现类

看到参数的区别也就明白了,rxJava 通过 map 操作,可以改变 Floawable 中数据的类型,而 flatMap 是根据 原有数据转成一个新的 Flowable类型了。一般来讲,flatMap 是根据之前的 Flowable 里面的数据进行二次转换。

算了,不继续解释 rxJava 中的 flatMap 了,想了解的去看其他文章吧。

结论强调kt 的 flatMap 是对集合的操作,是一个平铺操作;rxJava 的 flatMap 是将 数据转成 一个新的 数据源。二者没有共通的地方。(概念上是共通的,实际用法没有共通的地方)

你可能感兴趣的:(kotlin,android)