I'm creating a list of values, in a context where it so happens that, though the values are being added one at a time, the eventual number is known in advance. This is in a function that will be called many times, so the faster it runs, the better.
In Java, I would use the ArrayList constructor that specifies an initial capacity, because in theory this makes it slightly faster because it avoids resizing.
In Kotlin, one normally uses mutableListOf(), but this does not allow an initial capacity; in theory this should result in slightly slower code.
Is the recommended/idiomatic Kotlin solution in this case:
To use the MutableList interface we use its function called mutableListOf() or mutableListOf<E>(). The elements of MutableList follow the sequence of insertion order and contains index number same as array.
ArrayList is a class that happens to implement the MutableList interface. The only difference is that arrayListOf() returns the ArrayList as an actual ArrayList. mutableListOf() returns a MutableList, so the actual ArrayList is "disguised" as just the parts that are described by the MutableList interface.
I was actually confused with capacity and size. There is no implementation of using a default capacity MutableList currently in Kotlin stdlib.
You can make one yourself.
fun <T> mutableListWithCapacity(capacity: Int): MutableList<T> =
ArrayList(capacity)
// creates a MutableList of Int with capacity of 5.
val mutableList = mutableListWithCapacity<Int>(5)
One of the reason why mutableListOf does not allow for default capacity is because default values in kotlin is not null.
However there is a utility function defined in kotlin.collections
package.
public inline fun <T> MutableList(size: Int, init: (index: Int) -> T): MutableList<T> {
val list = ArrayList<T>(size)
repeat(size) { index -> list.add(init(index)) }
return list
}
You can create a List with a List function or MutableList function with a default capacity and its mapping.
// creates a list of ints with default capacity of 10 and having nulls.
// But I highly doubt you should initialize it with a null since Kotlin is a null-safe language.
val list = MutableList<Int?>(10) { null }
But since there should not be nulls in Kotlin if it is intended use of non-null list else you have to do a null check using operators like ?.
!!.
.
Fill an immutable list
val doubles = List(5) { i -> i * 2 }
result --> [0, 2, 4, 6, 8]
Fill a mutable list of five elements with zeros
val ints = MutableList(5) { 0 }
result --> [0, 0, 0, 0, 0]
You can wrap this mutableList()
predefined function in a function like the following
fun <E> emptyMutableList(size: Int = 0): MutableList<E?> {
return MutableList(size) {
null
}
}
this will return a MutableList
of size size
but also with null
assigned to all of its cells. Now if you want to access any index value, your program will not crash with java.lang.IndexOutOfBoundsException
like it would if you use the solution in the accepted answer. Here is what I mean:
fun <E> emptyMutableList(size: Int = 0): MutableList<E?> {
return MutableList(size) {
null
}
}
fun <T> mutableListWithCapacity(capacity: Int): MutableList<T> =
ArrayList(capacity)
fun main() {
val mutableList1 = mutableListWithCapacity<Int>(20)
val mutableList2 = emptyMutableList<Int>(20)
mutableList1[10] // this will throw a java.lang.IndexOutOfBoundsException
mutableList2[10] // this will not throw an exception but it will return null
}
Of course everything depends on how memory efficient vs crash-free you want your program to be.
Happy coding!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With