If I have a list like this one
var foo = mutableListOf("John", "Wayne")
and if I want to add an element on top of the list, so far I am thinking of two options.
First: foo.add(0, "Twyla")
Second: foo = (mutableListOf("Twyla") + foo).toMutableList()
I am not how the above two options fare in terms of performance but what is a recommended way in general?
There is an important difference between your 2 versions. The first modifies the original list, the second doesn’t.
fun List<String>.print() { forEach { print("$it, ") }; println() }
fun main() {
//sampleStart
val original = mutableListOf("John", "Wayne")
// your second example: this does not modify "original"
val foo = (mutableListOf("Twyla") + original).toMutableList()
original.print()
foo.print()
// your first version
original.add(0, "Twyla")
original.print()
//sampleEnd
}
As for performance, the first option is potentially far better. The second option creates a copy of the list, meaning it also copies every single element in the list, therefor this scales with the number of elements in the list (it copies references to each element to be precise, but this can still be expensive if the list is very big).
The performance of the first option is not defined as it depends on the implementation of List. In the worst case it will take as long as your second option. But if you use an implementation like LinkedList
you will get an operation which runs in constant time. So if you have to push an element to the front of the list very often you should probably use LinkedList
s over the default of ArrayList
which will result in the described worst case scenario.
What you say is 100% percent correct. There is one additional option. If you don’t need an actually mutable list you can use the fact that the readonly list interface doesn’t require a consistent backing implementation. This is what the immutableCollections prototype does: