1. 概述

本文将介绍如何在 Kotlin 中对数组进行相等性判断。

Kotlin 中的数组比较与 Java 不同,它提供了更语义化的操作符和函数,可以更直观地判断数组是否“相等”。我们将从基础开始,逐步讲解不同场景下的数组比较方式。


2. Kotlin 中的两种相等性

Kotlin 支持两种类型的相等性判断:

  • 引用相等(Referential Equality):判断两个变量是否指向同一个对象
  • 结构相等(Structural Equality):判断两个对象的值是否相等

使用方式如下:

  • === 用于引用相等判断
  • == 用于结构相等判断

我们先定义几个数组:

val first = arrayOf("java", "python", "kotlin")
val second = arrayOf("java", "python", "kotlin")
val third = first

✅ 引用相等测试

assert(first === third) // true,指向同一对象
assert(first === second) // false,不同对象实例

✅ 结构相等测试

assert(first == third) // true
assert(first == second) // false ❗️注意:结果可能不符合预期

⚠️ 虽然 firstsecond 内容一样,但 == 并不能正确判断数组的结构相等。这是 Kotlin 数组的特性,需要使用专门的方法来判断结构相等。


3. 使用 contentEquals 方法判断结构相等

Kotlin 提供了 contentEquals 方法来判断数组内容是否相等。这是一个 infix 函数,使用起来非常直观。

继续使用上面的数组:

assert(first contentEquals third) // true
assert(first contentEquals second) // true ✅

✅ 此时 firstsecond 虽然是两个不同对象,但内容一致,contentEquals 能正确返回 true

⚠️ 嵌套数组的问题

contentEquals 有一个限制:对嵌套数组只做浅比较(shallow comparison),即只比较外层数组元素的引用。

示例:

val r1 = arrayOf(arrayOf("R1", "R2"), arrayOf("R3", "R4"))
val r2 = arrayOf(arrayOf("R1", "R2"), arrayOf("R3", "R4"))
val r3 = r1

assert(r1 contentEquals r2) // false ❌

此时虽然内容一致,但因为嵌套数组的引用不同,所以返回 false


4. 使用 contentDeepEquals 实现深度比较

为了解决嵌套数组的比较问题,Kotlin 提供了 contentDeepEquals 函数,它会递归地比较数组中的每一个元素,包括嵌套数组。

继续使用上面的嵌套数组:

assert(r1 contentDeepEquals r2) // true ✅

✅ 现在可以正确判断嵌套数组的内容是否一致。

完整测试代码如下:

val r1 = arrayOf(arrayOf("R1", "R2"), arrayOf("R3", "R4"))
val r2 = arrayOf(arrayOf("R1", "R2"), arrayOf("R3", "R4"))
val r3 = r1

assert(r1 contentDeepEquals r3) // true
assert(r1 contentDeepEquals r2) // true
assert(r2 contentDeepEquals r3) // true

5. 用户自定义对象数组的比较

当数组中包含用户自定义类的实例时,contentEquals 的行为会受到类定义的影响。

❌ 普通类比较失败

我们定义一个 Person 类:

class Person(var name: String?, var age: Int?)
val first = arrayOf(Person("John", 20), Person("Mary", 15))
val second = arrayOf(Person("John", 20), Person("Mary", 15))

assert(first contentEquals second) // false ❌

原因:Person 类没有重写 equals() 方法,因此 contentEquals 只能做引用比较。

✅ 使用 data class 实现结构比较

Person 定义为 data class,Kotlin 会自动实现 equals()hashCode() 方法:

data class Person(var name: String?, var age: Int?)

val first = arrayOf(Person("John", 20), Person("Mary", 15))
val second = arrayOf(Person("John", 20), Person("Mary", 15))

assert(first contentEquals second) // true ✅

✅ 现在可以正确比较数组内容。

✅ 嵌套数组中对象的比较

我们也可以用 contentDeepEquals 来比较嵌套数组中的对象:

val p1 = arrayOf(arrayOf(Person("John", 20), Person("Mary", 15)))
val p2 = arrayOf(arrayOf(Person("John", 20), Person("Mary", 15)))

assert(p1 contentDeepEquals p2) // true ✅

6. 总结

本文我们介绍了 Kotlin 中数组相等性判断的几种方式:

方法 用途 是否支持嵌套数组 是否支持对象数组
== 结构相等
=== 引用相等
contentEquals 浅结构比较 ✅(需重写 equals()
contentDeepEquals 深结构比较 ✅(需重写 equals()

✅ 建议:

  • 比较基本类型数组用 contentEquals
  • 比较嵌套数组或对象数组时使用 contentDeepEquals
  • 自定义类建议使用 data class,避免手动实现 equals()

所有代码示例可在 GitHub 仓库 找到。



原始标题:Guide to Comparing Arrays in Kotlin