数组
数组是一种数据结构, 其中包含固定数量的值, 所有的值为同一个类型, 或这个类型的子类型. Kotlin 中最常见的数组类型是对象类型的数组, 使用 Array
类表达.
什么时候使用数组
当你需要满足某些特殊的低层级要求时, 可以在 Kotlin 中使用数组. 例如, 如果你的性能需求超过了通常的应用程序的需求, 或者需要构建自定义数据结构的情况. 如果你没有这种类型的限制, 请使用 集合(Collection).
集合与数组相比, 有以下优点:
集合是只读的, 因此给了你更多的控制权, 使你能够编写意图清晰的, 更加健壮的代码.
更容易对集合添加或删除元素. 与此相反, 数组的大小是固定的. 要对数组添加或删除元素, 只能每次创建新的数组, 这是非常效率低下的:
fun main() {
//sampleStart
var riversArray = arrayOf("Nile", "Amazon", "Yangtze")
// 使用 += 赋值操作创建新的 riversArray,
// 复制原来的元素, 并添加 "Mississippi"
riversArray += "Mississippi"
println(riversArray.joinToString())
// 输出结果为 Nile, Amazon, Yangtze, Mississippi
//sampleEnd
}
你可以使用相等操作符(==
) 来检查两个集合是否结构相等(Structurally Equal). 但不能对数组使用这个操作符. 相反, 你需要使用特殊的函数, 详情请参见 比较数组.
关于集合, 详情请参见 集合概述.
创建数组
在 Kotlin 中要创建数组, 你可以使用:
下面的示例使用 arrayOf()
函数, 并将数组元素的值传递给它:
fun main() {
//sampleStart
// 使用元素值 [1, 2, 3] 创建数组
val simpleArray = arrayOf(1, 2, 3)
println(simpleArray.joinToString())
// 输出结果为 1, 2, 3
//sampleEnd
}
下面的示例使用 arrayOfNulls()
函数创建指定大小的数组, 并使用 null
元素填充数组:
fun main() {
//sampleStart
// 使用元素值 [null, null, null] 创建数组
val nullArray: Array<Int?> = arrayOfNulls(3)
println(nullArray.joinToString())
// 输出结果为 null, null, null
//sampleEnd
}
下面的示例使用 emptyArray()
函数创建空数组:
var exampleArray = emptyArray<String>()
Array
构造器的参数是, 数组大小, 以及一个函数, 这个函数对指定的数组下标返回对应的元素值:
fun main() {
//sampleStart
// 创建一个 Array<Int>, 初始化为 0 值: [0, 0, 0]
val initArray = Array<Int>(3) { 0 }
println(initArray.joinToString())
// 输出结果为 0, 0, 0
// 创建一个 Array<String>, 初始化为 ["0", "1", "4", "9", "16"]
val asc = Array(5) { i -> (i * i).toString() }
asc.forEach { print(it) }
// 输出结果为 014916
//sampleEnd
}
嵌套的数组
数组可以相互嵌套, 创建多维数组:
fun main() {
//sampleStart
// 创建一个 2 维数组
val twoDArray = Array(2) { Array<Int>(2) { 0 } }
println(twoDArray.contentDeepToString())
// 输出结果为 [[0, 0], [0, 0]]
// 创建一个 3 维数组
val threeDArray = Array(3) { Array(3) { Array<Int>(3) { 0 } } }
println(threeDArray.contentDeepToString())
// 输出结果为 [[[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]]]
//sampleEnd
}
访问和修改元素
数组永远是可以修改的. 要访问和修改数组中的元素, 请使用 下标访问操作符[]
:
fun main() {
//sampleStart
val simpleArray = arrayOf(1, 2, 3)
val twoDArray = Array(2) { Array<Int>(2) { 0 } }
// 访问并修改元素
simpleArray[0] = 10
twoDArray[0][0] = 2
// 输出修改后的元素
println(simpleArray[0].toString()) // 输出结果为 10
println(twoDArray[0][0].toString()) // 输出结果为 2
//sampleEnd
}
Kotlin 中的数组是 不可变的(invariant). 这意味着 Kotlin 不允许你将一个 Array<String>
赋值给一个 Array<Any>
, 以防止发生运行时错误. 相反, 你可以使用 Array<out Any>
. 更多详情请参见, 类型投射.
使用数组
在 Kotlin 中, 你可以使用数组, 向一个函数传递不定数量的参数, 或对数组元素本身执行操作. 例如, 比较数组, 变换数组内容, 或转换为集合.
向一个函数传递不定数量的参数
在 Kotlin 中, 你可以通过 vararg
参数, 向一个函数传递不定数量的参数. 如果你不能预先知道参数的数量, 这个功能是很有用的, 例如格式化消息, 或者创建 SQL 查询的情况.
要向一个函数传递一个数组, 其中包含不定数量的参数, 请使用 展开(spread) 操作符 (*
). 展开操作符会将数组的每个元素作为独立的参数传递给指定的函数:
fun main() {
val lettersArray = arrayOf("c", "d")
printAllStrings("a", "b", *lettersArray)
// 输出结果为 abcd
}
fun printAllStrings(vararg strings: String) {
for (string in strings) {
print(string)
}
}
更多详情请参见 不定数量参数(varargs).
比较数组
要比较两个数组是否包含相同的元素, 并且顺序也相同, 请使用 .contentEquals()
和 .contentDeepEquals()
函数:
fun main() {
//sampleStart
val simpleArray = arrayOf(1, 2, 3)
val anotherArray = arrayOf(1, 2, 3)
// 比较数组内容
println(simpleArray.contentEquals(anotherArray))
// 输出结果为 true
// 使用中缀标记法(Infix notation), 在一个元素发生变化之后, 再次比较数组内容
simpleArray[0] = 10
println(simpleArray contentEquals anotherArray)
// 输出结果为 false
//sampleEnd
}
变换数组
Kotlin 有很多有用的函数, 可以对数组进行变换. 这篇文档重点介绍少数几个函数, 但并不是完整的功能列表. 关于所有函数的完整列表, 请参见我们的 API 参考文档.
求和
要得到一个数组中所有元素的和, 请使用 .sum()
函数:
fun main() {
//sampleStart
val sumArray = arrayOf(1, 2, 3)
// 对数组元素求和
println(sumArray.sum())
// 输出结果为 6
//sampleEnd
}
随机打乱
要随机打乱数组中的元素, 请使用 .shuffle()
函数:
fun main() {
//sampleStart
val simpleArray = arrayOf(1, 2, 3)
// 随机打乱元素 [3, 2, 1]
simpleArray.shuffle()
println(simpleArray.joinToString())
// 再次随机打乱元素 [2, 3, 1]
simpleArray.shuffle()
println(simpleArray.joinToString())
//sampleEnd
}
将数组转换为集合
如果你同时使用不同的 API, 其中一些使用数组, 另一些使用集合, 那么你可以将数组转换为 集合, 也可以反过来将集合转换为数组.
转换为 List 或 Set
要将数组转换为 List
或 Set
, 请使用 .toList()
和 .toSet()
函数.
fun main() {
//sampleStart
val simpleArray = arrayOf("a", "b", "c", "c")
// 转换为 Set
println(simpleArray.toSet())
// 输出结果为 [a, b, c]
// 转换为 List
println(simpleArray.toList())
// 输出结果为 [a, b, c, c]
//sampleEnd
}
转换为 Map
要将数组转换为 Map
, 请使用 .toMap()
函数.
只有元素类型为 Pair<K,V>
的数组能够转换为 Map
. Pair
实例的第 1 个值成为键(key), 第 2 个值成为值(value). 下面的示例使用 中缀标记法(Infix notation) 来调用 to
函数, 创建 Pair
的元祖:
fun main() {
//sampleStart
val pairArray = arrayOf("apple" to 120, "banana" to 150, "cherry" to 90, "apple" to 140)
// 转换为 Map
// 键(key)是水果, 值(value)是它们的卡路里数量
// 注意, 键必须是唯一的, 因此最后一个 "apple" 的值会覆盖第一个的值
println(pairArray.toMap())
// 输出结果为 {apple=140, banana=150, cherry=90}
//sampleEnd
}
基本类型(Primitive Type)数组
如果你使用 Array
类来存储基本类型(Primitive Type), 这些元素值会被装箱为对象. 另一种选择是, 你可以使用基本类型数组, 它可以让你在数组中存储基本类型, 而不会发生装箱操作导致的性能损失副作用:
这些类与 Array
类没有继承关系, 但它们有相同的一组函数和属性.
下面的示例创建一个 IntArray
类的实例:
fun main() {
//sampleStart
// 创建一个数组, 元素类型为 Int, 大小为 5, 元素值为 0
val exampleArray = IntArray(5)
println(exampleArray.joinToString())
// 输出结果为 0, 0, 0, 0, 0
//sampleEnd
}
下一步做什么?
为什么对大多数使用场景我们推荐使用集合, 请阅读我们的 集合概述.
学习其他 基本类型.
如果你是 Java 开发者, 请阅读我们的 Java 到 Kotlin 迁移向导, 关于 集合 的部分.
最终更新: 2024/10/17