一、集合
1.1、只读集合与可变集合
Kotlin 的集合设计和 Java 不同的另一项特性是:Kotlin 把访问数据的接口和修改集合数据的接口分开了,kotlin.collections.Collection
接口提供了遍历集合元素、获取集合大小、判断集合是否包含某元素等操作,但这个接口没有提供添加和移除元素的方法。kotlin.collections.MutableCollection
接口继承于 kotlin.collections.Collection
接口,扩展出了用于添加、移除、清空元素的方法
就像 kotlin 对 val
和 var
的区分一样,只读集合接口与可变集合接口的分离能提高对代码的可控性,如果函数接收 Collection
作为形参,那么就可以知道该函数不会修改集合,而只是对数据进行读取
以下是用来创建不同类型集合的函数
集合元素 | 只读 | 可变 |
---|---|---|
List | listOf | mutableListOf、arrayListOf |
Set | setOf | mutableSetOf、hashSetOf、linkedSetOf、sortedSetOf |
Map | mapOf | mutableMapOf、hashMapOf、linkedMapOf、sortedMapOf |
val list = listOf(10, 20, 30, 40)
//不包含 add 方法
//list.add(100)
println(list.size)
println(list.contains(20))
val mutableList = mutableListOf("leavesC", "叶应是叶", "叶")
mutableList.add("Ye")
println(mutableList.size)
println(mutableList.contains("leavesC"))
1.2、集合与 Java
因为 Java 并不会区分只读集合与可变集合,即使 Kotlin 中把集合声明为只读的, Java 代码也可以修改这个集合,而 Java 代码中的集合对 Kotlin 来说也是可变性未知的,Kotlin 代码可以将之视为只读的或者可变的,包含的元素也是可以为 null 或者不为 null 的
例如,在 Java 代码中 names 这么一个 List 类型的变量
public class JavaMain {
public static List<String> names = new ArrayList<>();
static {
names.add("leavesC");
names.add("Ye");
}
}
在 Kotlin 中可以用以下四种方式来引用变量 names
val list1: List<String?> = JavaMain.names
val list2: List<String> = JavaMain.names
val list3: MutableList<String> = JavaMain.names
val list4: MutableList<String?> = JavaMain.names
1.3、只读集合的可变性
只读集合不一定就是不可变的。例如,假设存在一个拥有只读类型接口的对象,该对象存在两个不同的引用,一个只读,一个可变,当可变引用修改了该对象后,这对只读引用来说就相当于“只读集合被修改了”,因此只读集合并不总是线程安全的。如果需要在多线程环境下处理数据,需要保证正确地同步了对数据的访问,或者使用支持并发访问的数据结构
例如,list1 和 list1 引用到同一个集合对象, list3 对集合的修改同时会影响到 list1
val list1: List<String> = JavaMain.names
val list3: MutableList<String> = JavaMain.names
list1.forEach { it -> println(it) } //leavesC Ye
list3.forEach { it -> println(it) } //leavesC Ye
for (index in list3.indices) {
list3[index] = list3[index].toUpperCase()
}
list1.forEach { it -> println(it) } //LEAVESC YE
1.4、集合与可空性
集合的可空性可以分为三种:
- 可以包含为 null 的集合元素
- 集合本身可以为 null
- 集合本身可以为 null,且可以包含为 null 的集合元素
例如,intList1 可以包含为 null 的集合元素,但集合本身不能指向 null;intList2 不可以包含为 null 的集合元素,但集合本身可以指向 null;intList3 可以包含为 null 的集合元素,且集合本身能指向 null
//List<Int?> 是能持有 Int? 类型值的列表
val intList1: List<Int?> = listOf(10, 20, 30, 40, null)
//List<Int>? 是可以为 null 的列表
var intList2: List<Int>? = listOf(10, 20, 30, 40)
intList2 = null
//List<Int?>? 是可以为 null 的列表,且能持有 Int? 类型值
var intList3: List<Int?>? = listOf(10, 20, 30, 40, null)
intList3 = null