Cloning Lists in Kotlin: How to Avoid Messing Up with References?
\n\nImagine: you're writing a Kotlin application, processing a list of data, and suddenly the original array changes on its own. Sound familiar? Most likely, you just copied a reference, not the list itself. In this article, we'll cover all the legitimate ways to clone a list in Kotlin — from shallow copy to deep copy. No fluff, just code and explanations.
\n\nThis topic is inspired by a popular Stack Overflow question (over 200,000 views): "How to clone or copy a list in kotlin". Let's finally figure out how to properly copy a Kotlin list without losing data or losing your mind.
\n\nWhy Doesn't Simple Assignment Work?
\n\nIn Kotlin, as in Java, lists are reference types. If you write:
\n\nval original = mutableListOf("A", "B", "C")\nval copy = original // This is NOT a copy!\ncopy.add("D")\nprintln(original) // [A, B, C, D] — the original changed!\n\nYou've simply created a second reference to the same object in memory. Any modification through copy will affect original. To avoid this, you need to use special methods for copying a Kotlin list.
Top 5 Ways to Copy a List in Kotlin
\n\nWe'll cover all the main options: from simple toList() to manual deep copying. Choose the one that fits your task.
1. toList() — The Simplest Way
\n\nThe toList() method creates a new immutable copy of the list. This is a shallow copy — the elements themselves are not duplicated, but the list structure becomes independent.
val original = listOf("Kotlin", "Java", "Python")\nval copy = original.toList()\n\n// copy is a new object\nprintln(copy === original) // false — different references\nprintln(copy == original) // true — same content\n\nPerfect for simple lists of strings or numbers. If you need a mutable copy, use toMutableList().
2. toMutableList() — For Mutable Copies
\n\nWant a copy you can modify? toMutableList() is your choice. It creates a new MutableList with the same elements.
val original = listOf(1, 2, 3)\nval mutableCopy = original.toMutableList()\nmutableCopy.add(4)\n\nprintln(original) // [1, 2, 3]\nprintln(mutableCopy) // [1, 2, 3, 4] — original untouched\n\nThis is the most popular way to clone a mutable list in Kotlin.
\n\n3. ArrayList(collection) — Java Classic
\n\nIf you come from Java, this method will feel familiar. The ArrayList constructor takes another collection and copies its elements.
val original = listOf("A", "B", "C")\nval arrayCopy = ArrayList(original)\narrayCopy[0] = "Z"\n\nprintln(original) // [A, B, C]\nprintln(arrayCopy) // [Z, B, C]\n\nWorks quickly and predictably. But remember: this is also a shallow copy.
\n\n4. map() — With Element Transformation
\n\nIf you need not just to copy but also to transform elements, use map(). It creates a new list based on the old one, applying a lambda to each element.
val numbers = listOf(10, 20, 30)\nval doubled = numbers.map { it * 2 }\n\nprintln(numbers) // [10, 20, 30]\nprintln(doubled) // [20, 40, 60]\n\nFor simple copying without changes, you can write numbers.map { it }, but that's redundant — better use toList().
5. Deep Copy for Complex Objects
\n\nAll previous methods perform a shallow copy. If your list contains mutable objects (e.g., a data class with fields), modifying an object in the copy will affect the original: