集合的可空性
集合的可空性包括两个方面,集合本身的可空性和集合元素的可空性。
List<Int>?
:List 本身可空,List 的元素不可空
List<Int?>
:List 本身不可空,List 的元素可空
List<Int?>?
:List 本身可空,List 的元素也可空
有一个实用方法 filterNotNull,可以遍历一个包含可空值的集合并过滤掉其中的空值:
fun addValidNumbers(numbers: List<Int?>) {
val validNumbers = numbers.filterNotNull() // 此时 validNumbers 就是 List<Int> 类型的了
}
只读集合与可变集合
Kotlin 把 Java 集合中访问数据和修改数据的接口分开了。
MutableCollection 继承了 Collection 并增加了修改集合内容的方法。
Kotlin 喜欢把可变和不可变分清楚,就像 val 和 var 之间的分离一样,只读集合接口和可变集合接口的分离让程序中数据发生的事情更容易理解。
这里需要牢记的一个关键点是,只读集合不一定是不可变的
。
如上图所示,可能只读集合的引用和可变集合的引用,都指向同一个集合对象,这时该集合的可变性就不能保证了。
Kotlin 集合与 Java
每一种 Java 集合在 Kotlin 中都有两种表示:一种是只读的,一种是可变的。
同样的,Map 也被分为了 Map 和 MutableMap。
集合创建函数:
集合类型 | 只读 | 可变 |
---|---|---|
List | listOf | mutableListOf、arrayListOf |
Set | setOf | mutableSetOf、hashSetOf、linkedSetOf、sortedSetOf |
Map | mapOf | mutableMapOf、hashMapOf、linkedMapOf、sortedMapOf |
在 java 中使用 Kotlin 集合
在 java 中使用 Kotlin 集合时,如一个 java 方法接收一个集合参数,这时使用 kotlin 中的可变集合和不可变集合作为实参都是可以的,因为 java 并不知道它是可变的还是不可变的。
所以,当你向可以修改集合的 Java 代码传递集合时,你需要采用特别的预防措施,来确保 Kotlin 类型正确地反映出集合上所有可能的修改。
在 Kotlin 中使用 Java 集合
与基本数据类型一样,在 Kotlin 中,Java 的集合类型的变量,会被视为平台类型,即一个自身可空性未知、元素可空性未知、可变性未知
的集合。
当需要重写 Java 中的方法或是实现一个接口时,需要自己判断,决定使用哪一种 Kotlin 类型来表示 Java 方法中的集合类型。
这需要根据需求,具体情况,具体分析。
对象和基本数据类型的数组
默认情况下,应该优先使用集合,但当然,数组也有它的用处。
要在 Kotlin 中创建数组,可以使用以下方法:
// Array<Int>
val a = arrayOf(1, 2, 3) // [1, 2, 3]
val b = arrayOfNulls<Int?>(3) // [null, null, null]
val c = Array(3) { it * 2 } // [0, 2, 4]
// Array<String>
val s = arrayOf("a", "b", "c") // ["a", "b", "c"]
通过这样的方法生成的 Array<Int>,相当于 Java 中的 Integer[]。如果需要 int[] 这样的基本数据类型数组,需要使用 Kotlin 中的 IntArray 类进行创建,ByteArray、CharArray、BooleanArray 与之类似。
val a = IntArray(3) // [0, 0, 0]
val b = intArrayOf(1, 2, 3) // [1, 2, 3]
val c = IntArray(3) { it * 2 } // [0, 2, 4]
能对集合的操作基本也都适用于数组(filter、map 等)。
数组转化为集合:toList
集合转化为数组:toIntArray