Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin MutableList initial capacity

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:

  1. Go ahead and use the ArrayList constructor; ArrayList is a perfectly valid MutableList.
  2. Ignore the issue; the initial capacity never actually makes a measurable difference to speed.
  3. Something else?
like image 740
rwallace Avatar asked May 09 '20 14:05

rwallace


People also ask

How does Kotlin define MutableList?

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.

What is the difference between ArrayList and MutableList in Kotlin?

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.


3 Answers

Updated Answer

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)

Outdated Answer

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 ?. !!..

like image 114
Animesh Sahu Avatar answered Oct 24 '22 17:10

Animesh Sahu


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]
like image 36
Barakuda Avatar answered Oct 24 '22 16:10

Barakuda


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!

like image 33
AouledIssa Avatar answered Oct 24 '22 15:10

AouledIssa