1-数组

fun 1-数组()

创建数组

Kotlin 创建数组大致有如下两种方式。

  1. 使用 arrayOf()、 arrayOfNulls()、 emptyArray()工具函数。

  2. 使用 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 要求元素必须是引用类型,当向其中存入基本类型的值时,Kotlin 会自动将这些基本类型装箱为对应的包装类实例,然后再存入数组。
为避免频繁装箱带来的性能开销,Kotlin 提供了专门的数组类型来对应 Java 的基本类型数组:

  • 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> 对象,其中每个元素都包含 index 和 value 两个属性。 通过 for-in 遍历时,即可直接访问数组的索引和值。

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官网