如何在Kotlin散列表中强制键的对象等价?

wgeznvg7  于 2022-11-25  发布在  Kotlin
关注(0)|答案(3)|浏览(154)

我有一个类'Foo'(不受我的控制),我想用它作为Kotlin(java)散列表中的键。问题是'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)]
jogvjijk

jogvjijk1#

考虑使用IdentityHashMap-它是相同的Map,但它只比较键的引用。
还要注意,为了有效地使用常规HashMap,键类不仅必须考虑equals,还必须考虑hashCode

kxeu7u2r

kxeu7u2r2#

我将使用@AterLux回答,但我张贴我一直在使用的评论。

data class Identity<T>(private val delegate: T) {
    override fun equals(other: Any?): Boolean {
        return delegate === other
    }
}
fun <K,V> mutableIdentityMapOf(): MutableMap<Identity<K>,V> {
    return mutableMapOf()
}

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

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

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

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

wgx48brx3#

对于您的特定情况和目标JVM,IdentityHashMap可能是最佳选择,正如@AterLux所建议的那样。
如果我们需要多平台解决方案,或者我们有一个更一般的情况,即更改第三方类的equals()逻辑,我们可以简单地使用我们自己的 Package 器作为密钥:

data class FooKey(val foo: Foo) {
    override fun equals(other: Any?) = foo === (other as? FooKey)?.foo
}

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

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

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

相关问题