1. 概述

本文将深入讲解如何在 Kotlin 中处理多维数组。我们会先简要回顾 Kotlin 的 Array 类型,然后重点介绍多维数组的创建与访问方式。

对于有经验的开发者来说,数组是再熟悉不过的基础结构。但在 Kotlin 中,由于其独特的类型系统和语法糖,多维数组的使用方式与 Java 或其他语言略有不同,稍不注意就容易踩坑✅。掌握这些细节,能让你在图像处理、矩阵运算等场景中更加得心应手。

2. 一维数组基础

Kotlin 中的 数组 是一种内置的泛型类 Array<T>,用于存储相同类型的元素集合。我们通常通过构造函数来初始化数组,该构造函数接收两个参数:数组大小和一个初始化 lambda 表达式。

public class Array<T> {
   //...
   public inline constructor(size: Int, init: (Int) -> T)
}

其中 T 是泛型类型参数,允许我们创建任意类型的数组。举个例子,假设我们有一个表示像素的 data class:

data class Pixel(val red: Int, val green: Int, val blue: Int)

val pixelArray: Array<Pixel> = Array(10) { Pixel(
   (0..255).random(),
   (0..255).random(),
   (0..255).random())
}

上面代码创建了一个包含 10 个随机颜色像素的一维数组。每个 RGB 分量都在 0~255 范围内,组合起来可生成约 1677 万种颜色。

访问数组元素可以直接使用下标语法(即 []),这是 Kotlin 对 get()set() 方法的重载:

for(i in 0..9){
    print(pixelArray[i]) // 输出类似 "Pixel(red=123, green=45, blue=67)"
    Assertions.assertThat((pixelArray[i].red in 0..255))
    Assertions.assertThat((pixelArray[i].blue in 0..255))
    Assertions.assertThat((pixelArray[i].green in 0..255))
}

可以把这个一维数组想象成一条由 10 个彩色像素组成的水平线:

pixelarray

3. 多维数组构建与使用

要在 Kotlin 中创建二维或更高维度的数组,核心思路是:用数组嵌套数组。也就是说,二维数组的本质是一个数组,其每个元素又是另一个数组。

比如我们要创建一个 10×10 的像素矩阵(可以理解为一张小图片):

val matrix: Array<Array<Pixel>> = Array(10) {
    Array(10) {
        Pixel(
            (0..255).random(),
            (0..255).random(),
            (0..255).random()
        )
    }
}

✅ 这里外层 Array(10) 创建了 10 行,每行由内层 Array(10) 构造出一个包含 10 个像素的数组。

遍历并打印所有像素值:

for (i in 0..9) {
    for (j in 0..9) {
        print(matrix[i][j])
        Assertions.assertThat((matrix[i][j].red in 0..255))
        Assertions.assertThat((matrix[i][j].blue in 0..255))
        Assertions.assertThat((matrix[i][j].green in 0..255))
    }
    println()
}

通过 matrix[i][j] 即可访问第 i 行 j 列的像素,相当于二维坐标 (x=i, y=j)。

可视化结构如下:

matrix

扩展到三维也是一样的逻辑——数组套数组再套数组:

val video: Array<Array<Array<Pixel>>> = Array(10) {
    Array(10) {
        Array(10) {
            Pixel(
                (0..255).random(),
                (0..255).random(),
                (0..255).random()
            )
        }
    }
}
for (i in 0..9) {
    for (j in 0..9) {
        for(k in 0..9) {
            print(video[i][j][k])
            Assertions.assertThat((video[i][j][k].red in 0..255))
            Assertions.assertThat((video[i][j][k].blue in 0..255))
            Assertions.assertThat((video[i][j][k].green in 0..255))
        }
        println()
    }
    println("---")
}

⚠️ 注意三层嵌套带来的性能开销。这种结构适合模拟“随时间变化的图像”——X/Y 是空间维度,Z 可视为帧序列的时间轴。

4. 基本类型多维数组优化

当处理基本数据类型(如 Int, Boolean 等)时,直接使用 Array<Array<Int>> 会导致装箱/拆箱开销,影响性能❌。

Kotlin 提供了专用的原生数组类型来避免这个问题:

  • IntArrayint[](JVM 层面对应)
  • DoubleArray
  • BooleanArray
  • LongArray

我们可以结合 arrayOf()intArrayOf() 快速构建高效的二维整型数组:

val first: Array<IntArray> = arrayOf(
    intArrayOf(2, 4, 6), // 第一行三个元素
    intArrayOf(1, 3, 5)  // 第二行三个元素
)

✅ 这样每一行都是真正的 int[],没有对象包装,内存更紧凑,访问更快。

如果需要创建非规则矩阵(各行长度不同),可以用 arrayOfNulls 配合手动初始化:

val arrayNulls = arrayOfNulls<Array<Int>>(2)
arrayNulls[0] = Array(3) { 0 }
arrayNulls[1] = Array(2) { 1 }

最终得到一个两行的不规则数组:

  • 第一行:[0, 0, 0]
  • 第二行:[1, 1]

⚠️ 注意此时仍是 Array<Int> 的数组,若追求极致性能建议统一使用 IntArray 替代 Array<Int>

5. 使用 Multik 库简化操作

对于科学计算、机器学习等涉及大量多维数组运算的场景,推荐使用 JetBrains 官方推出的 Multik 库。它提供了类似 NumPy 的 API,极大简化了张量操作。

Gradle 依赖配置

implementation "org.jetbrains.kotlinx:multik-core:0.2.2"
implementation "org.jetbrains.kotlinx:multik-default:0.2.2"

Maven 依赖配置

<dependency>    
   <artifactId>multik-core</artifactId>    
   <groupId>org.jetbrains.kotlinx</groupId>    
   <version>0.2.2</version>    
</dependency>    
<dependency>    
   <artifactId>multik-core-jvm</artifactId>    
   <groupId>org.jetbrains.kotlinx</groupId>    
   <version>0.2.2</version>    
</dependency>    
<dependency>    
   <artifactId>multik-default</artifactId>    
   <groupId>org.jetbrains.kotlinx</groupId>    
   <version>0.2.2</version>    
</dependency>    
<dependency>    
   <artifactId>multik-default-jvm</artifactId>    
   <groupId>org.jetbrains.kotlinx</groupId>    
   <version>0.2.2</version>    
</dependency>

✅ Multik 支持自动广播、切片、数学运算等高级功能,在处理大规模数据时比原生数组方便得多。例如创建一个 3×3 的浮点矩阵并求转置,几行代码即可完成。

不过对于简单业务逻辑,仍建议使用原生数组以减少依赖复杂度。

6. 总结

本文系统梳理了 Kotlin 中多维数组的实现方式:

  • ✅ 多维数组本质是数组的嵌套:Array<Array<T>>
  • ✅ 访问使用 arr[i][j][k] 下标语法,直观易懂
  • ⚠️ 基本类型优先使用 IntArray 等原生数组避免装箱
  • ✅ 不规则数组可用 arrayOfNulls 动态构建
  • ✅ 复杂数值计算推荐引入 Multik 库提升开发效率

所有示例代码均已上传至 GitHub:https://github.com/example/kotlin-arrays-demo 可自由参考使用。


原始标题:Multidimentional Arrays in Kotlin