Collections

List, Set and Map, Mutable and Read-Only

Kotlin has three collection families: List (ordered, duplicates allowed), Set (unique elements) and Map (unique keys). Each is a pair of interfaces: List<T> only reads (size, get, contains), while MutableList<T> adds add, remove and set. Create them with listOf or mutableListOf, setOf or mutableSetOf, and mapOf or mutableMapOf. Here is the shared catalog; build each example with it, as in kotlinc Books.kt Kinds.kt -include-runtime -d kinds.jar && java -jar kinds.jar.

BookNest's six books as a read-only list (Books.kt)Kotlin
data class Book(val id: Int, val title: String, val genre: String, val price: Double,
  val rating: Double, val pages: Int, val inStock: Boolean)
val books = listOf(
  Book(1, "The Quiet Harbor", "Fiction", 14.99, 4.6, 312, true),
  Book(2, "Patterns of the Deep Web", "Technology", 39.50, 4.3, 428, true),
  Book(3, "Salt and Saffron", "Cooking", 24.00, 4.8, 256, false),
  Book(4, "Small Steps to Big Summits", "Travel", 18.75, 4.1, 198, true),
  Book(5, "The Clockmaker's Paradox", "Science Fiction", 16.20, 4.5, 344, true),
  Book(6, "Gardens in Glass", "Home and Garden", 21.30, 4.4, 176, true),
)
Read-only is a view, not a frozen copy (Kinds.kt)Kotlin
fun main() {
  val cart = mutableListOf(books[0], books[4], books[0])   // MutableList<Book>
  val view: List<Book> = cart                              // same object, read-only type
  val ids: Set<Int> = cart.map { it.id }.toSet()
  val byId: Map<Int, Book> = books.associateBy { it.id }
  println("${view.size} lines, distinct ids $ids, book 3 is ${byId[3]?.title}")
  cart.clear()                                             // view sees it too
  println("view.size = ${view.size}, byId[9] = ${byId[9]}")
  // view.add(books[1])   // does not compile: unresolved reference 'add'
}
Output
3 lines, distinct ids [1, 5], book 3 is Salt and Saffron
view.size = 0, byId[9] = null

Read-only is not immutable: view has no add, yet it changed when cart did, so a ViewModel that exposes a MutableList as List still leaks mutations. Equality is structural (Data Classes): listOf(1, 2) == mutableListOf(1, 2) is true, and sets ignore order. Map lookups are nullable: byId[9] is Book? (Null Safety). Expose read-only types, and keep the MutableList private to the class that owns it.