Kotlin DISCUSSION

Array, IntArray, List and MutableList in Kotlin: which should hold a buffer of samples?

Started by rusell Kotlin IntArrayArray vs ListMutableListboxing overheadread-only collections
5 replies 248 views 6 participants
Latest activity · 30 Sep 2026

Array, IntArray, List and MutableList in Kotlin: which should hold a buffer of samples?

rusell Kotlin Forum
#1

I need to keep a buffer of 100,000 integer samples in a Kotlin program and pass it between a few functions. I can declare it as Array<Int>, IntArray, List<Int> or MutableList<Int>, and they all seem to work with for loops and map.

What are the real differences in memory, mutability and type behaviour, and is a List declared with val actually immutable?

Community replies 5

Re: Array, IntArray, List and MutableList in Kotlin: which should hold a buffer of samples?

#2

On the JVM, IntArray is a primitive int[]: 100,000 samples take about 400 kB in one contiguous block. Array<Int> is an Integer[], an array of references to boxed objects, and List<Int> (normally an ArrayList underneath) stores boxed values too. Each element then costs a reference plus a separate object with its own header, which comes to several times the memory, and reading a value means following a pointer.

For a numeric buffer, IntArray, DoubleArray and the other primitive arrays are the right choice.

Re: Array, IntArray, List and MutableList in Kotlin: which should hold a buffer of samples?

#3

Arrays have a fixed size but their elements can always be reassigned: buf[0] = 5 works on any array. List<T> is a read-only interface: it has get and size but no add or set. MutableList<T> adds those and can grow.

val has nothing to do with any of this. It only fixes which object the variable refers to. val samples = mutableListOf(1, 2) can still have elements added, and var samples = listOf(1, 2) can be pointed at a different list.

Re: Array, IntArray, List and MutableList in Kotlin: which should hold a buffer of samples?

#4

Read-only is not the same as immutable. A List<Int> reference may point at a list that someone else holds as a MutableList<Int>: after val m = mutableListOf(1, 2) and val r: List<Int> = m, calling m.add(3) makes r.size equal to 3. The interface only stops changes through that particular reference.

If a function must keep a stable copy, take one with toList(), which creates a new list. The same applies when a class hands out an internal list: expose it as List, and return a copy if callers must not see later changes.

Re: Array, IntArray, List and MutableList in Kotlin: which should hold a buffer of samples?

#5

Type behaviour differs as well. List<out T> is covariant, so a List<Int> can be passed where a List<Number> is expected. Array<T> is invariant: an Array<Int> is not an Array<Number>, which prevents the runtime store errors Java arrays allow.

Equality is a common trap: == on lists compares contents, but on arrays it compares references. intArrayOf(1, 2) == intArrayOf(1, 2) is false; use contentEquals. For the same reason an array property inside a data class does not take part in equals the way you would expect.

Re: Array, IntArray, List and MutableList in Kotlin: which should hold a buffer of samples?

#6

Creation and conversion in practice: IntArray(100_000) gives zeros, IntArray(8) { it * 2 } fills from the index, intArrayOf(1, 2, 3) lists values. arrayOf(1, 2, 3) creates the boxed Array<Int>, which is rarely what you want for numbers. Convert with toList(), toIntArray() and toTypedArray(); each makes a copy.

Be aware that collection operations such as map and filter on an IntArray return a List<Int>, boxing every element. In a hot path over a large buffer, use an index loop or for (v in buf), plus the primitive-returning helpers like sum() and average().

TEP COMMUNITY