Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I need invoke toList() when I launch flatMap in kotlin?

Tags:

android

kotlin

I can get a correct result when I use my.flatMap {it.toList()}.

I think that the val my is a List<String>, so I needn't to invoke toList(), but the code var ok3=my.flatMap { it } can't be compiled, why?

And more, the code var ok2=my.flatMap { bb } get an error result, why?

Code 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

Result

enter image description here

To Naetmul:

Thanks!

Why do you think that it is String type in the code val ok3=my.flatMap { it }

In my mind, it should be my type in the lambda expression, and my is List<String> type.

Image enter image description here

like image 422
HelloCW Avatar asked Dec 01 '25 01:12

HelloCW


1 Answers

Sidenote: If you do not re-assign, val is more preferred than var.


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

Here, the type of my is List<String>, and its elements are "abc" and "cef".

The type of bb is List<String> because List is transformed into List,
and its elements are "abc" and "cef".

i.e., my and bb are equivalent, although they are different instances. You do not need bb.


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

This is similar to

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 }

This is similar to

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")
}

So, ok2 = bb + bb (the for-loop is iterated twice because my has 2 elements.)
which means ok2 = listOf("abc", "cef") + listOf("abc", "cef")
which means ok2 = listOf("abc", "cef", "abc", "cef")


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

This is similar to

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 must be the List type. However, it is String type, the type does not match. So, compile error!


If you need to concatenate a List of String, you can use joinToString() method.
val my = listOf("abc", "cef")
val concat = my.joinToString("") // insert empty string between elements.

Refer to the Kotlin standard library document of List.

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

Returns a single list of all elements yielded from results of transform function being invoked on each element of original collection.

Assume a variable list has the type List<T>.

If we want to execute val newList = list.flatMap(function), then

function should have the function type (T) -> Iterable<R>.
(function's parameter is T-type, and it retuns Iterable<R>. List is a subtype of Collection, and Collection is a subtype ofIterable, soListis a subtype ofIterable`.)

newList will have the type List<R>.

it in the question will be the parameter of function.

So, it will be T-type, not List<T>-type.
i.e., it will be String-type, not List<String>-type.

like image 120
Naetmul Avatar answered Dec 05 '25 15:12

Naetmul



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!