A read-only collection interface lets code inspect a collection without offering mutation operations through that reference. In Kotlin, Collection, List, Set, and Map have read-only forms by default; mutable counterparts such as MutableCollection and MutableList add operations that change contents. This separation makes a function’s intent visible in its parameter types: Collection<T> says it reads items, while MutableCollection<T> says it may change them. section 8.2.2 section 8.2.3
Copy from a read-only source into a mutable target
fun <T> copyElements(source: Collection<T>, target: MutableCollection<T>) { for (item in source) target.add(item) } The source supports traversal but cannot be passed where a mutable target is required. The target explicitly permits add, so callers can see which argument will be modified before reading the implementation. section 8.2.2 section 8.2.2
Read-only does not mean immutable. A read-only reference may point at a mutable collection that another reference can change. Code using that view cannot mutate the collection itself, but it can still observe concurrent changes, including ConcurrentModificationException problems. Protect shared access with synchronization or concurrent-capable data structures when needed. Make a defensive copy before giving internal state to code that requires a MutableCollection. section 8.2.2 section 8.2.2
Kotlin uses the standard Java collection classes, so collections normally move between Kotlin and Java without conversion, wrappers, or copying. Kotlin presents each Java collection interface as read-only and mutable Kotlin representations; mutable interfaces correspond to Java-style mutation APIs. This interoperability does not guarantee safety: a Java method can mutate a value passed as List, even when Kotlin code holds it through a read-only type. section 3.1 section 8.2.3
Choose a collection type according to the operations a function needs:
- Use List, Set, Map, or Collection when the function only reads, traverses, or queries supplied data. section 8.2.2
- Use MutableList, MutableSet, MutableMap, or MutableCollection when the function must add, remove, or otherwise modify contents. section 8.2.3
- Use listOf, setOf, and mapOf for read-only interface results; use mutable creation functions when mutation is part of the intended API. section 8.2.3
- Treat Java-declared collection parameters as unknown mutability when implementing or overriding Java methods, and choose Kotlin types based on whether modification is intended. section 8.2.4
Figure 8.7 The hierarchy of the Kotlin collection interfaces. The Java classes ArrayList and HashSet, among others, extend Kotlin mutable interfaces.
The interface hierarchy shows the central rule: each mutable collection interface extends its corresponding read-only interface while adding mutation operations. section 8.2.3
Read-only collections also affect operator use. + and - produce a new collection. With += or -=, mutable collections are changed in place, whereas a read-only collection gets a modified copy and therefore needs a var reference for reassignment. section 9.1.2
