用相同的hashcode值和equals = true时,hashmap返回null null
我将类型问题的对象用作哈希图中的密钥。我实现了hashcode()
和等于
函数,如下所示。
Question.kt
@Parcelize
@Entity(primaryKeys = ["id"])
data class Question(
val id: Int,
val question:String
) : Parcelable{
@Ignore
@IgnoredOnParcel
var isQuestionDimmed: Boolean = false
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as Question
if (id != other.id) return false
if (isQuestionDimmed != other.isQuestionDimmed) return false
return true
}
override fun hashCode(): Int {
var result = id
result = 31 * result + isQuestionDimmed.hashCode()
return result
}[![enter image description here][1]][1]
}
fun Question.clone(): Question {
val question = Question(id,question)
question.isQuestionDimmed = isQuestionDimmed
return question
}
现在我创建了我的hashmap:
val hm:LinkedHashMap<Question, QuestionAnswerDetails> = hashMapOf()
现在,我希望当我尝试获取特定键的值时,hashmap将使用hashcode()和等于()函数引擎盖以找到预先插入的值。
这总是有效的,除非我修改了密钥的“ iSquestionDimmed”属性。然后,此之后,获取该钥匙总是返回null!尽管键存在,并且具有与我正在搜索的密钥对象相同的哈希码,并且equals()函数返回true。
I am using objects of type Question as the keys in a HashMap. I implemented the hashCode()
and equals
functions as shown below.
Question.kt
@Parcelize
@Entity(primaryKeys = ["id"])
data class Question(
val id: Int,
val question:String
) : Parcelable{
@Ignore
@IgnoredOnParcel
var isQuestionDimmed: Boolean = false
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as Question
if (id != other.id) return false
if (isQuestionDimmed != other.isQuestionDimmed) return false
return true
}
override fun hashCode(): Int {
var result = id
result = 31 * result + isQuestionDimmed.hashCode()
return result
}[![enter image description here][1]][1]
}
fun Question.clone(): Question {
val question = Question(id,question)
question.isQuestionDimmed = isQuestionDimmed
return question
}
Now I create my HashMap as such:
val hm:LinkedHashMap<Question, QuestionAnswerDetails> = hashMapOf()
Now, I expect that when I try to fetch the value of a certain key, the HashMap would use the hashCode() and equals() functions under the hood to locate the pre-inserted value.
This always works, except if I modify a key's "isQuestionDimmed" property. Then, after that, fetching that key always returns null! Although the key exists and has the same hashCode as the key object I am searching with and the equals() function returns true.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在hashmaps中使用对象作为键时,您必须确保满足以下条件:
多亏了@cactustictictacs
为什么override equals()和hashcode()和hashcode()
? ()和hashcode()对象类的方法和该类的对象用作映射的键或Java中的设置,使用这些方法的默认实现,仅检查参考平等。 参考因此,您只能使用与最初添加该值完全相同的密钥对象访问MAP值。
为什么在hashcode()和equals()实现中使用的关键对象属性是不可变的?
,因为当首先定义值v1到k1时,为(k1,v1)分配的内存中的位置取决于(k1,v1)在哈希码中,根据k1的哈希码,将第一次(K1,v1)添加到哈希图中。如果您以后修改HashCode()中使用的K1属性,则其哈希码将变得不同,但是(K1,V1)中的内存位置将根据K1的原始哈希码保持相同。因此,如果修改后尝试使用K1获取哈希图,则结果将是无效的,因为它将指向内存中的新位置,而没有分配给它。对于Equals()而言,它使用的属性应该是不变的,以便能够仅维护hashmap中的唯一键。
如何修复上述代码?
幸运的是,由于Kotlin的数据类可为您提供仅在主构造函数中使用属性的HashCode()和Equals()的默认实现,因此我们可以简单地将代码重写如下。 :
现在,您可以自由地更改
iSqueStionDimmed
的值When using objects as keys in HashMaps, you have to make sure that you satisfy the below conditions:
Updated thanks to @cactustictacs
Why override equals() and hashCode()?
If a class does not override the equals() and hashCode() methods of the Object class and an object of such class is used as a key for map or set in Java, the default implementation of these methods is used which simply checks for reference equality. Reference Thus, you will only be able to access Map values using the exact same key object which you used to add the value originally.
Why should the key object properties used in hashCode() and equals() implementation be immutable?
Because, when first defining let’s say value v1 to k1, the place in memory assigned for (k1,v1) depends on the hashcode calculated the first time (k1,v1) is added to the hashMap according to the hashcode of k1. If you later modify a k1 property that is used in hashCode(), its hashcode will become different but the place in memory for (k1,v1) will remain the same according to the original hashcode of k1. Thus, if you try to fetch the hashmap using k1 after modifying it, the result will be null as it will point to a new location in memory with nothing assigned to it. Same thing for equals(), the properties used in it should be immutable to be able to maintain only unique keys in the HashMap.
How to fix the above code?
Luckily, since Kotlin's data classes give you default implementations of hashCode() and equals() that only use the properties in the primary constructor, we can simply rewrite the code as follows:
Now, you can change the value of
isQuestionDimmed
freely