TL;DR 检查data class Data
的内容:它是否覆盖了equals
函数?Data
类的任何成员是否是非基本类型并覆盖了equals
函数?阅读更多解释和示例。
如何在Kotlin中实现equals/hashcode函数?
您是完全正确的,对于常规类,如果我们想通过值而不是引用来比较两个对象,则必须重写equals
和hashCode
函数。 equals
函数的实现可以是您喜欢的任何内容。这完全取决于应用程序的业务逻辑和在您的特定情况下被视为“相等”的内容。
您的实现实际上已经足够好了。基本上检查标识(也称为按引用比较,===
Kotlin运算符),检查other
是否是相同的实例类,其他任何内容都取决于业务逻辑。
hashCode
函数的实现可以使用您在equals
函数中比较的相同成员,但是使用类的其他成员也可以。
注意:通常认为最好同时重写equals
和hashCode
函数。即使hashCode
在您的代码中没有直接使用,它也可以在您使用的某些库的实现中使用。如果两个对象相等,则它们的哈希码也必须相等。如果对象未更改,则哈希码必须保持不变。
为什么两个列表可能不相等?
我不确定,但问题可能出在Data
数据类或其成员的值中。
我运行了两个简单的测试,一个是基本类型,另一个是类似于以下内容的data class Data
:
测试#1
var list1: List<Int> = listOf(1,2,3,4)
var list2: List<Int> = arrayListOf(1,2,3,4)
var list3: List<Int> = LinkedList<Int>().also { it.addAll(listOf(1,2,3,4)) }
fun equals(): Boolean {
return list1 == list3 && list1 == list2 && list2 == list3
}
println(equals())
测试 #2
data class Data(var i: Int = 0)
var list1: List<Data> = listOf(Data(1),Data(2),Data(3),Data(4))
var list2: List<Data> = arrayListOf(Data(1),Data(2),Data(3),Data(4))
var list3: List<Data> = LinkedList<Data>().also { it.addAll(listOf(Data(1),Data(2),Data(3),Data(4))) }
fun equals(): Boolean {
return list1 == list3 && list1 == list2 && list2 == list3
}
println(equals())
在这两种情况下,打印输出都是
true
。这是因为Kotlin文档中指出:
如果两个列表具有相同的大小并且在相同位置上具有结构相等的元素,则认为它们是相等的。
参见
文档引用。 结构相等性在
此处有所描述。现在,这是修改后的
Data
类,并且在
equals
方法的实现中发生了一些奇怪的事情:
data class Data(var i: Int = 0) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as Data
return (i + other.i) % 2 == 1
}
}
如果您尝试比较按相同顺序添加
Data
对象的相同列表,则这些列表不会相等,因为两个
Data
对象的比较有时会返回
false
。如果
Data
类包含另一种非基本类型,并且它的
equals
方法对于实际上相等的对象不返回
true
,那么这也可能是问题所在。等等。
GroupWithData
拥有不同类型的List
(例如一个ArrayList
和一个LinkedList
),但是按照相同顺序持有相同元素,您是否认为它们相等? - giddsList
是一个接口,因此它需要实现该接口的某个类。它应该实现equals()
方法来比较内容 - 或者更可能是继承自例如AbstractList
的类。但如果它没有这样做,那就可以解释你的问题。) - gidds