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.
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),
)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'
}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.