Is Iterable.toList guaranteed to make a copy?


#1

Is Iterable.toList guaranteed to make a (shallow) copy? Even if the Iterable in question is already a list?

If yes, is this documented somewhere?

If not (or maybe even if yes…), what is the idiomatic way to make a shallow copy of a collection?


#2

Maybe something like

list.map { it }

#3

toList could return the same instance if the Iterable is actually an immutable list. Otherwise it returns a shallow copy.

fun main() {
    val list = emptyList<Any>()
    val list2 = list.toList()
    println(list === list2)
}

#4

Thanks for the responses!

Out of curiosity, what constitutes an “immutable list”? The above example prints “false” if I replace the first line with val list = listOf(1, 2, 3)


#5

Based of what I can tell by the implementation

public fun <T> Iterable<T>.toList(): List<T> {
    if (this is Collection) {
        return when (size) {
            0 -> emptyList()
            1 -> listOf(if (this is List) get(0) else iterator().next())
            else -> this.toMutableList()
        }
    }
    return this.toMutableList().optimizeReadOnlyList()
}

the part about immutable is not true. As long as the list is empty it will always return emptyList() which is a singleton object. In all other cases it should be a shallow copy. (Well I guess EmptyList is immutable but yeah :wink:)


The code is from kotlin 1.3.11but I don’t think this part has changed since 1.0 and probably never will.


#6

No, it shouldn’t. It is currently, but nothing says that it should necessary be so.

We don’t have the means to determine if a list is actually immutable, but when we do toList implementation will just return the receiver for such lists:

if (this is ImmutableList) return this
...

#7

You’re right. I didn’t mean to imply that it’s guaranteed. I just meant to say that it currently returns a copy in those cases.

I’d be interested to see how this could be achieved. I guess you could check for whether some ImmutableList interface is present, but that would only catch kotlin implementations. This wouldn’t for example catch Guavas immutable lists. I guess you will only support the immutable types from this KEEP.