# 集合
與某些語言不同,Kotlin 將可變與不可變的集合(list、set、map等等)區分開來。在集合可編輯時對精確控制有助于排隊 bug,并為其設計了良好的 API。
理解一個可變集合的只讀_視圖_,和一個絕對不可變的集合間的差異非常重要。兩者都易于創建,但類型系統并不清楚其差異,因此你要你保持對它的跟蹤(如果有意義的話)。
Kotlin 的 `List<out T>` 類型是一個提供了像 `size`、`get` 之類只讀操作的接口。與 Java 相似,它從 `Collection<T>` 繼承并依次地從 `Iterable<T>` 繼承。改變列表的方法通過 `MutableList<T>` 接口加入。這種模式同樣適用于 `Set<out T>/MutableSet<T>` 和 `Map<K, out V>/MutableMap<K, V>`。
下面我們來看一看 list 和 set 的基礎用法
``` kotlin
val numbers: MutableList<Int> = mutableListOf(1, 2, 3)
val readOnlyView: List<Int> = numbers
println(numbers) // 打印 "[1, 2, 3]"
numbers.add(4)
println(readOnlyView) // 打印 "[1, 2, 3, 4]"
readOnlyView.clear() // -> 不會編譯
val strings = hashSetOf("a", "b", "c", "c")
assert(strings.size == 3)
```
Kotlin 沒有專門的語法結構來創建 list 或 set。使用標準庫的像 `listOf()`、`mutableListOf()`、`setOf()`、`mutableSetOf`方法。創建沒有性能風險的映射的代碼可以使用一個簡單的[范例](idioms.html#read-only-map):`mapOf(a to b, c to d)`
注意這個 `readOnlyView` 變量指向相同的 list 并應 list 的改變而改變。如果一個 list 只存在只讀的引用,我們可以認為這個集合是完全不可變的。創建這樣的集合的方式很簡單,就像這樣:
``` kotlin
val items = listOf(1, 2, 3)
```
當前,這個 `listOf` 方法是使用數組列表的實現,但在將來能利用它們知道它們不可能改變的事實返回更有內存效率的完全不可變的集合。
注意只讀類型是[協變的](generics.html#variance)。意思是說,假定 Rectangle 繼承自 Shap,你就可以帶上一個 `List<Rectangle>` 并且把它賦值給 `List<Shape>`。這對于可變集合類型來說是不允許的,因為它會導致運行時故障。
有時你想要回頭調取一個集合在某個時間點的快照,要保證它沒有改變:
``` kotlin
class Controller {
private val _items = mutableListOf<String>()
val items: List<String> get() = _items.toList()
}
```
`toList` 擴展復制了列表項,因此,返回的列表可以的保證未被改變。
list 和 set 上還有各種各樣很有用的擴展方法,常用的有:
``` kotlin
val items = listOf(1, 2, 3, 4)
items.first == 1
items.last == 4
items.filter { it % 2 == 0 } // 返回 [2, 4]
rwList.requireNoNulls()
if (rwList.none { it > 6 }) println("No items above 6")
val item = rwList.firstOrNull()
```
...還有你所希望的 sort、zip、fold、reduce 等等實用工具。
映射沿用相同的模式。它們可以被簡單地實例化并像這樣訪問:
``` kotlin
val readWriteMap = hashMapOf("foo" to 1, "bar" to 2)
println(map["foo"])
val snapshot: Map<String, Int> = HashMap(readWriteMap)
```