[关闭]
@cxm-2016 2016-12-28T18:44:16.000000Z 字数 1897 阅读 1823

Kotlin (二十二)——集合

Kotlin

版本:1
翻译:李颖


集合(Collection)

与很多其他语言不同, Kotlin 明确地区分可变的和不可变的集合(list, set, map, 等等). 明确地控制集合什么时候可变什么时候不可变, 对于消除 bug 是很有帮助的, 也有助于设计出良好的 API.

理解可变集合的只读 视图(view) 与一个不可变的集合之间的差别, 是很重要的. 这两者都可以很容易地创建, 但类型系统无法区分这二者的差别, 因此记住哪个集合可变哪个不可变, 这是你自己的责任.

Kotlin 的 List<out T> 类型是一个只读的接口, 它提供的操作包括 size, get 等等. 与 Java 一样, 这个接口继承自 Collection<T>, Collection<T> 又继承自 Iterable<T>. 能够修改 List 内容的方法是由 MutableList<T> 接口添加的. 对于 Set<out T>/MutableSet<T> 以及 Map<K, out V>/MutableMap<K, V> 也是同样的模式.

通过下面的例子, 我们可以看看 list 和 set 类型的基本用法:

  1. val numbers: MutableList<Int> = mutableListOf(1, 2, 3)
  2. val readOnlyView: List<Int> = numbers
  3. println(numbers) // 打印结果为: "[1, 2, 3]"
  4. numbers.add(4)
  5. println(readOnlyView) // 打印结果为: "[1, 2, 3, 4]"
  6. readOnlyView.clear() // -> 无法编译
  7. val strings = hashSetOf("a", "b", "c", "c")
  8. assert(strings.size == 3)

Kotlin 没有专门的语法用来创建 list 和 set. 你可以使用标准库中的方法, 比如 listOf(), mutableListOf(), setOf(), mutableSetOf().
在并不极端关注性能的情况下, 创建 map 可以使用一个简单的 惯用法: mapOf(a to b, c to d)

注意, readOnlyView 变量指向的其实是同一个 list 实例, 因此它的内容会随着后端 list 一同变化. 如果指向 list 的只有唯一一个引用, 而且这个引用是只读的, 那么我们可以这个集合完全是不可变的. 创建一个这样的集合的简单办法如下:

  1. val items = listOf(1, 2, 3)

目前, listOf 方法是使用 array list 实现的, 但在将来, 这个方法会返回一个内存效率更高的, 完全不可变的集合类型, 以便尽量利用集合内容不可变这个前提.

注意, 只读集合类型是 协变的(covariant). 也就是说, 假设 Rectangle 继承自 Shape, 你可以将一个 List<Rectangle> 类型的值赋给一个 List<Shape> 类型变量. 但这对于可变的集合类型是不允许的, 因为可能导致运行时错误.

有时候, 你希望向调用者返回集合在某个时刻的一个快照, 而且这个快照保证不会变化:

  1. class Controller {
  2. private val _items = mutableListOf<String>()
  3. val items: List<String> get() = _items.toList()
  4. }

toList 扩展方法只是单纯地复制 list 内的元素, 因此, 返回的 list 内容可以确保不会变化.

list 和 set 还有一些有用的扩展方法, 值得我们熟悉一下:

  1. val items = listOf(1, 2, 3, 4)
  2. items.first() == 1
  3. items.last() == 4
  4. items.filter { it % 2 == 0 } // 返回值为: [2, 4]
  5. val rwList = mutableListOf(1, 2, 3)
  6. rwList.requireNoNulls() // 返回值为: [1, 2, 3]
  7. if (rwList.none { it > 6 }) println("No items above 6") // 打印结果为: "No items above 6"
  8. val item = rwList.firstOrNull()

... 此外还有你所期望的各种工具方法, 比如 sort, zip, fold, reduce 等等.

Map 也遵循相同的模式. 可以很容易地创建和访问, 比如:

  1. val readWriteMap = hashMapOf("foo" to 1, "bar" to 2)
  2. println(readWriteMap["foo"]) // 打印结果为: "1"
  3. val snapshot: Map<String, Int> = HashMap(readWriteMap)
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注