I was writing a small piece of code in which I internally handle my data in a mutable map, which in turn has mutable lists.
I wanted to expose my data to the API use
Currently in Kotlin stdlib there are no implementations of List (Map) that would not also implement MutableList (MutableMap). However due to Kotlin's delegation feature the implementations become one liners:
class ImmutableList(private val inner:List) : List by inner
class ImmutableMap(private val inner: Map) : Map by inner
You can also enhance the creation of the immutable counterparts with extension methods:
fun Map.toImmutableMap(): Map {
if (this is ImmutableMap) {
return this
} else {
return ImmutableMap(this)
}
}
fun List.toImmutableList(): List {
if (this is ImmutableList) {
return this
} else {
return ImmutableList(this)
}
}
The above prevents a caller from modifying the List (Map) by casting to a different class. However there are still reasons to create a copy of the original container to prevent subtle issues like ConcurrentModificationException:
class ImmutableList private constructor(private val inner: List) : List by inner {
companion object {
fun create(inner: List) = if (inner is ImmutableList) {
inner
} else {
ImmutableList(inner.toList())
}
}
}
class ImmutableMap private constructor(private val inner: Map) : Map by inner {
companion object {
fun create(inner: Map) = if (inner is ImmutableMap) {
inner
} else {
ImmutableMap(hashMapOf(*inner.toList().toTypedArray()))
}
}
}
fun Map.toImmutableMap(): Map = ImmutableMap.create(this)
fun List.toImmutableList(): List = ImmutableList.create(this)
While the above is not hard to implement there are already implementations of immutable lists and maps in both Guava and Eclipse-Collections.