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 ❗️注意:结果可能不符合预期
⚠️ 虽然 first
和 second
内容一样,但 ==
并不能正确判断数组的结构相等。这是 Kotlin 数组的特性,需要使用专门的方法来判断结构相等。
3. 使用 contentEquals
方法判断结构相等
Kotlin 提供了 contentEquals
方法来判断数组内容是否相等。这是一个 infix 函数,使用起来非常直观。
继续使用上面的数组:
assert(first contentEquals third) // true
assert(first contentEquals second) // true ✅
✅ 此时 first
和 second
虽然是两个不同对象,但内容一致,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 仓库 找到。