首页 > 解决方案 > 在 Kotlin 中,HashSet 包含通过哈希重复的元素

问题描述

我有一个声明如下的变量:

val done = HashSet<StudentProgrammeState>()

在处理结束时,检查如下:

if (done.distinctBy { it.hashCode() }.size < done.size ) {
    println("Duplicate states were evaluated.")
}

每次运行都会出现此消息。既然done是 a HashSet,它怎么可能包含多个与 不同的项目HashCode

以下是 的相等方法StudentProgrammeState

class StudentProgrammeState(val program: Program) {
    val instances = HashSet<StudentModuleInstance>()

    override fun equals(other: Any?): Boolean {
        if (!(other is StudentProgrammeState)) return false
        return (other.program == program) && 
          (other.instances.containsAll(instances) && 
          instances.containsAll(other.instances))
    }
    override fun hashCode() = Objects.hash(program, instances)

Equals这里不直接检查hashCodeofinstances但该测试应该对应于无序集相等。

对于 studentModuleInstance:

typealias StudentModuleInstance = Pair<Module, Int>

由于Pair<>是内置的data class,它应该有一个 Kotlin 生成equalshashcode方法。

对于所考虑的所有实例,的值program设置为相同。

标签: kotlinset

解决方案


HashSet.add()提供了这个合约:

如果指定的元素尚不存在,则将其添加到此集合中。更正式地说,如果此集合不包含元素 e2,则将指定的元素 e 添加到此集合中,使得 (e==null ? e2==null : e.equals(e2))。如果该集合已包含该元素,则调用将保持该集合不变并返回 false。

特别hashCode是没有提到。hashCode 唯一性与 add 方法无关:具有相同哈希码的多个项目进入一个哈希集。

具有相同 hashCode 但不等于的项目将最终在同一个存储桶中,这会降低get()这些项目的性能。但除此之外,hashCode 并不重要。


推荐阅读