Search code examples
kotlindata-class

Defensive copy of a mutable collection in Kotlin data class


I want to have a data class accepting a read-only list:

data class Notebook(val notes: List<String>) {
}

But it can accept MutableList as well, because it is a subtype of the List.

For example the following code modifies the passed in list:

fun main(args: Array<String>) {
    val notes = arrayListOf("One", "Two")
    val notebook = Notebook(notes)

    notes.add("Three")

    println(notebook)       // prints: Notebook(notes=[One, Two, Three])
}

Is there a way how perform defensive copy of the passed in list in the data class?


Solution

  • I think better is to use JetBrains library for immutable collections - https://github.com/Kotlin/kotlinx.collections.immutable

    Import in your project

    Add the bintray repository:

    repositories {
        maven {
            url "http://dl.bintray.com/kotlin/kotlinx"
        }
    }
    

    Add the dependency:

    compile 'org.jetbrains.kotlinx:kotlinx-collections-immutable:0.1'
    

    Result:

    data class Notebook(val notes: ImmutableList<String>) {}
    
    fun main(args: Array<String>) {
        val notes = immutableListOf("One", "Two")
        val notebook = Notebook(notes)
    
        notes.add("Three") // creates a new collection
    
        println(notebook)       // prints: Notebook(notes=[One, Two])
    }
    

    Note: You also can use add and remove methods with ImmutableList, but this methods doesn't modify current list just creates new one with your changes and return it for you.