# 集合
与某些语言不同,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)
```