在Kotlin中启动flatMap时,为什么需要调用toList()?

时间:2018-07-16 03:15:18

标签: android kotlin

使用my.flatMap {it.toList()}可以得到正确的结果。

我认为val myList<String>,因此不需要调用toList(),但是代码var ok3=my.flatMap { it }无法编译,为什么?

还有,代码var ok2=my.flatMap { bb }会得到错误结果,为什么?

代码A

var my=listOf("abc","cef")
var bb=my.toList()

var ok1=my.flatMap {it.toList()}
var ok2=my.flatMap { bb }
//var ok3=my.flatMap { it }  //It's wrong

结果

enter image description here

致Naetmul:

谢谢!

您为什么认为在代码it中输入Stringval ok3=my.flatMap { it }

在我看来,lambda表达式中的it类型应为my,而my的类型应为List<String>

图片 enter image description here

2 个答案:

答案 0 :(得分:3)

旁注:如果您不重新分配,则valvar更为可取。


val my = listOf("abc","cef")
val bb = my.toList()

这里,my的类型为List<String>,其元素为"abc""cef"

bb的类型为List<String>,因为List转换为List
其元素为"abc""cef"

,即mybb是等效的,尽管它们是不同的实例。您不需要bb


var ok1 = my.flatMap {it.toList()}

这类似于

var ok1 = listOf<Char>() // empty List
for (it in my) {
    // `it` is the `String` type.
    // For the 1st iteration, it = "abc"
    // For the 2nd iteration, it = "cef"

    val chars: List<Char> = it.toList() // String is transformed into List of Chars

    ok1 = ok1 + chars
}

var ok2 = my.flatMap { bb }

这类似于

var ok2 = listOf<String>() // empty List
for (it in my) {
    // `it` is the `String` type.
    // For the 1st iteration, it = "abc"
    // For the 2nd iteration, it = "cef"

    ok2 = ok1 + bb // You know, bb = listOf("abc, "cef")
}

因此,ok2 = bb + bb(因为my有2个元素,所以for循环被迭代了两次。)
表示ok2 = listOf("abc", "cef") + listOf("abc", "cef")
这意味着ok2 = listOf("abc", "cef", "abc", "cef")


val ok3=my.flatMap { it }  //It's wrong

这类似于

var ok3 = listOf<?>() // empty List
for (it in my) {
    // `it` is the `String` type.
    // For the 1st iteration, it = "abc"
    // For the 2nd iteration, it = "cef"

    ok3 = ok3 + it
}

ok3必须是List类型。但是,itString类型,类型不匹配。 所以,编译错误!


如果需要连接List中的String,可以使用joinToString()方法。

val my = listOf("abc", "cef")
val concat = my.joinToString("") // insert empty string between elements.

请参阅Kotlin standard library document of List

fun <T, R> Iterable<T>.flatMap(
    transform: (T) -> Iterable<R>
): List<R>
     

返回从的结果产生的所有元素的单个列表   在原始元素的每个元素上调用转换函数   集合。

假设变量list的类型为List<T>

如果我们要执行val newList = list.flatMap(function),那么

function应该具有函数类型(T) -> Iterable<R>
function的参数是T类型,它会重新调整Iterable<R>ListCollection的子类型,并且Collection is a subtype of是Iterable { {1}}列表, so可重复使用。)

is a subtype of的类型为newList

问题中的

List<R>将是it的参数。

因此,function将是it类型,而不是T类型。
List<T>将是it类型,而不是String类型。

答案 1 :(得分:1)

1。

var my=listOf("abc","cef")
var ok1=my.flatMap {it.toList()}
//var ok3=my.flatMap { it }  //It's wrong

在这种情况下:
-flatMapA转换为Iterable<>
-it的类型是String
-String.toList()返回List<Char>

var ok3=my.flatMap { it }是错误的,因为您需要像String那样将Iterable<>转换为List<>

2。

var ok2=my.flatMap { bb } get an error result

my有2个元素,因此my.flatMap { bb }对返回bb进行了两次操作。
返回两次{"abc","cef","abc","cef"}

后,您将获得bb