You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何强制Kotlin HashMap的键使用对象等价性?

问题

我有一个不受控制的类Foo,希望将其用作Kotlin(Java)HashMap的键。问题在于Foo的equals方法实现的是值等价性,这对我的场景来说过于宽松,我需要的是对象等价性。我尝试了如下代码:

data class Foo(val prop: String)
data class Bar(val prop: String)

fun main() {
    val fooMap = mutableMapOf<Any, Bar>()

    val fooA = Foo("common value")
    val fooB = Foo("common value")

    fooMap[fooA] = Bar("different A")
    fooMap[fooB] = Bar("different B")
    println("${fooMap.keys} ${fooMap.values}")
}

结果fooMap中只有一个条目,但我期望有两个:

[Foo(prop=common value)] [Bar(prop=different B)]
解决方案

1. 使用Java的IdentityHashMap

IdentityHashMap完全基于对象的引用相等性判断键是否相同,直接忽略类自身实现的equals和hashCode方法,在Kotlin中可直接使用:

data class Foo(val prop: String)
data class Bar(val prop: String)

fun main() {
    val fooMap = java.util.IdentityHashMap<Foo, Bar>()

    val fooA = Foo("common value")
    val fooB = Foo("common value")

    fooMap[fooA] = Bar("different A")
    fooMap[fooB] = Bar("different B")
    println("${fooMap.keys} ${fooMap.values}")
}

运行后会输出两个独立条目,符合预期。

2. 自定义引用相等的包装类

创建不重写equals和hashCode的包装类(默认实现基于引用相等),将Foo实例作为包装类属性,用包装类作为Map的键:

data class Foo(val prop: String)
data class Bar(val prop: String)

class IdentityWrapper<T>(val value: T)

fun main() {
    val fooMap = mutableMapOf<IdentityWrapper<Foo>, Bar>()

    val fooA = Foo("common value")
    val fooB = Foo("common value")

    fooMap[IdentityWrapper(fooA)] = Bar("different A")
    fooMap[IdentityWrapper(fooB)] = Bar("different B")
    println("${fooMap.keys.map { it.value }} ${fooMap.values}")
}

这种方法可继续使用Kotlin标准库的MutableMap实现,通过包装类规避原类的equals逻辑。

3. 使用Kotlin的引用相等策略(1.4+)

从Kotlin 1.4开始,mutableMapOf支持传入EqualityPolicy.reference,直接指定Map使用引用相等判断键:

data class Foo(val prop: String)
data class Bar(val prop: String)

fun main() {
    val fooMap = mutableMapOf<Foo, Bar>(equalityPolicy = EqualityPolicy.reference)

    val fooA = Foo("common value")
    val fooB = Foo("common value")

    fooMap[fooA] = Bar("different A")
    fooMap[fooB] = Bar("different B")
    println("${fooMap.keys} ${fooMap.values}")
}

该方法语法简洁,无需依赖Java集合或自定义包装类,是Kotlin环境下的首选方案之一。


内容的提问来源于stack exchange,提问作者phreed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 08:25:21