1-数组
创建数组
Kotlin 创建数组大致有如下两种方式。
使用 arrayOf()、 arrayOfNulls()、 emptyArray()工具函数。
使用 Array(size: Int, init: (Int) -> T)构造器 。 代码示例
fun main() {
// =========================
// 方式1:使用工具函数
// =========================
// 1.1 arrayOf() 创建普通数组
val array1 = arrayOf(1, 2, 3, 4, 5)
println("arrayOf: ${array1.joinToString()}") // 输出: 1, 2, 3, 4, 5
// 1.2 arrayOfNulls() 创建可存放 null 的数组
val array2 = arrayOfNulls<String>(5)
println("arrayOfNulls: ${array2.joinToString()}") // 输出: null, null, null, null, null
// 1.3 emptyArray() 创建空数组
val array3 = emptyArray<Int>()
println("emptyArray: ${array3.joinToString()}") // 输出: 空
// =========================
// 方式2:使用 Array 构造器
// =========================
// Array(size, init) 通过 lambda 初始化数组
val array4 = Array(5) { i -> i * i } // 0*0, 1*1, 2*2, 3*3, 4*4
println("Array(size, init): ${array4.joinToString()}") // 输出: 0, 1, 4, 9, 16
// 也可以用更简洁的 lambda
val array5 = Array(5) { it + 1 } // it 为索引
println("Array with index: ${array5.joinToString()}") // 输出: 1, 2, 3, 4, 5
}
代码解释:
使用 arrayOf() 函数
不需要显式指定数组长度,但需依次列出每个数组元素。
相当于 Java 中的静态初始化数组。
由于程序已经提供了每个元素,Kotlin 可以自动推断数组元素类型,因此无需在 arrayOf() 上指定泛型。 使用 arrayOfNulls
(size) 函数 需要显式指定数组长度,所有元素初始值为 null。
相当于 Java 中的动态初始化数组。
由于元素初始值是 null,Kotlin 无法推断元素类型,因此必须在函数上指定泛型 T。 使用 emptyArray
() 函数 创建一个长度为 0 的空数组。
因为没有元素,所以必须显式指定数组元素类型的泛型。 使用 Array(size: Int, init: (Int) -> T) 构造器
需要显式指定数组长度。
可通过 Lambda 表达式动态生成每个元素的值(Java 原生数组不支持这种方式)。
由于 Array
ByteArray → byte[]
ShortArray → short[]
IntArray → int[]
LongArray → long[]
CharArray → char[]
FloatArray → float[]
DoubleArray → double[]
BooleanArray → boolean[] 这些专用数组可直接存储基本类型值,避免了装箱操作,提高了性能。
fun main() {
// 使用 Array<T> 存储基本类型,会自动装箱为 Integer(Int 的包装类)
val numbers: Array<Int> = arrayOf(1, 2, 3)
println("Array<Int> 内容: ${numbers.joinToString()}")
// 使用 IntArray,直接存储基本类型,性能更高
val intNumbers: IntArray = intArrayOf(1, 2, 3)
println("IntArray 内容: ${intNumbers.joinToString()}")
// 其他基本类型数组示例
val doubleNumbers: DoubleArray = doubleArrayOf(1.1, 2.2, 3.3)
println("DoubleArray 内容: ${doubleNumbers.joinToString()}")
val booleanFlags: BooleanArray = booleanArrayOf(true, false, true)
println("BooleanArray 内容: ${booleanFlags.joinToString()}")
}
使用数组 在 Kotlin 中,访问数组元素主要包括取值和赋值操作。 访问方式是通过在数组变量后加方括号 []
,其中方括号内写索引值。
注意:Kotlin 中的方括号操作符本质上是调用
get(index)
和set(index, value)
方法。arr[i]
实际上调用的是arr.get(i)
arr[i] = value
实际上调用的是arr.set(i, value)
获取到数组元素后,就可以像使用普通变量一样对其进行操作。 数组元素的类型与数组声明时指定的类型一致。
Kotlin 的数组索引从 0 开始,第一个元素索引为 0,最后一个元素索引为 数组长度 - 1。 示例代码
fun main() {
val numbers = arrayOf(1, 2, 3, 4, 5)
// 取值
println(numbers.get(0)) // 输出 1
println(numbers[0]) // 输出 1
// 赋值
numbers[1] = 20
println(numbers[1]) // 输出 20
}
上面 4 行粗体字代码分别示范了访问数组元素和修改数组元素。访问、修改数组元素时既 可使用 [index] 的方式来实现,也可使用 get(index)、 set( index, value)的方式来实现。这两种方式 的本质是一样的,而且编译器经过编译优化之后,还是会转换成根据数组的内存地址来访问数 组元素,因此性能不会有任何损失。
访问数组元素时,如果指定的索引值小于 0,或者大于等于数组长度,编译阶段不会报错,但运行时会抛出异常
java.lang.ArrayIndexOutOfBoundsException: N //N就是我们尝试访问的数组索引
所有的数组都提供了 一个 size 属性,通过这个属性可以访问到数组的长度,一旦获得了 数组的长度,就可以通过循环来遍历该数组的每个数组元素。
fun main() {
val ints = intArrayOf(1, 2, 3)
println("${ints.size}") //3
for(i in 0 until ints.size) {
println(ints[i])
} //1\n2\n3\n
}
使用for-in遍历数组
fun main() {
val ints = intArrayOf(1, 2, 3, 4, 5)
for(int in ints) {
println(int)
}//1\n2\n3\n4\n5\n
}
注意事项:
使用for-in 循环来遍历数组元素或集合元素时,不允许对循环变量进行赋值 。
对数组使用 for-in 循环依然会被编译成使用基于索引的循环,井不会创建迭代器进行遍历, 因此使用 for-in 循环遍历数组依然具有很好的性能 。
使用数组索引
前面使用索引遍历数组时还使用了 O until ints.size 这种方式来创建区间,其实完全没这 个必要,因为 Kotlin 的数组还提供了 一个 indices 属性,该属性即可返回数组的索引区间 。
for(index in ints.indices) {
println(ints[index])
}
这种通过索引区间遍历的实现具有更好的性能,因此 Kotlin 将会在底层将其编译成根据 内存地址来访问数组元素,因此不需要额外创建区间对象。 此外,程序还可使用 in、!in 来检查某个索引是否位于数组的索引区间内 通过lastIndex可以访问数组最后一位元素,相当于size-1
在需要同时获取数组的索引和值时,可以使用数组的 withIndex() 方法。 该方法会返回一个 Iterable
fun main() {
val arr = arrayOf("Java", "Kotlin", "Go")
// 使用 withIndex() 同时访问索引和值
for ((index, value) in arr.withIndex()) {
println("索引: $index, 元素: $value")
}
}
/*
输出:
索引: 0, 元素: Java
索引: 1, 元素: Kotlin
索引: 2, 元素: Go
*/
数组的常用方法
请参考Kotlin官网