Kotlin集合
集合
與大多數語言不同,Kotlin 區分可變集合和不可變集合(lists、sets、maps 等)。精確控制什麼時候集合可編輯有助於消除 bug 和設計良好的 API。
預先了解一個可變集合的只讀 視圖 和一個真正的不可變集合之間的區別是很重要的。它們都容易創建,但類型系統不能表達它們的差別,所以由你來跟蹤(是否相關)。
Kotlin 的 List<out T>
類型是一個提供只讀操作如 size
、get
等的接口。和 Java 類似,它繼承自 Collection<T>
進而繼承自 Iterable<T>
。改變 list 的方法是由 MutableList<T>
加入的。這一模式同樣適用於 Set<out T>/MutableSet<T>
及 Map<K, out V>/MutableMap<K, V>
。
我們可以看下 list 及 set 類型的基本用法:
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()
。
在非性能關鍵代碼中創建 map 可以用一個簡單的慣用法來完成:mapOf(a to b, c to d)
注意上面的 readOnlyView
變量(譯者注:與對應可變集合變量 numbers
)指向相同的底層 list 並會隨之改變。 如果一個 list 只存在只讀引用,我們可以考慮該集合完全不可變。創建一個這樣的集合的一個簡單方式如下:
val items = listOf(1, 2, 3)
目前 listOf
方法是使用 array list 實現的,但是未來可以利用它們知道自己不能變的事實,返回更節約內存的完全不可變的集合類型。
注意這些類型是協變的。這意味着,你可以把一個 List<Rectangle>
賦值給 List<Shape>
假定 Rectangle 繼承自 Shape。對於可變集合類型這是不允許的,因爲這將導致運行時故障。
有時你想給調用者返回一個集合在某個特定時間的一個快照, 一個保證不會變的:
class Controller {
private val _items = mutableListOf<String>()
val items: List<String> get() = _items.toList()
}
這個 toList
擴展方法只是複製列表項,因此返回的 list 保證永遠不會改變。
List 和 set 有很多有用的擴展方法值得熟悉:
val items = listOf(1, 2, 3, 4)
items.first() == 1
items.last() == 4
items.filter { it % 2 == 0 } // 返回 [2, 4]
val rwList = mutableListOf(1, 2, 3)
rwList.requireNoNulls() // 返回 [1, 2, 3]
if (rwList.none { it > 6 }) println("No items above 6") // 輸出「No items above 6」
val item = rwList.firstOrNull()
…… 以及所有你所期望的實用工具,例如 sort、zip、fold、reduce 等等。
Map 遵循同樣模式。它們可以容易地實例化和訪問,像這樣:
val readWriteMap = hashMapOf("foo" to 1, "bar" to 2)
println(readWriteMap["foo"]) // 輸出「1」
val snapshot: Map<String, Int> = HashMap(readWriteMap)