Kotlin 集合:您可以选择按身份键数据 类 吗?

Kotlin collections: Can you optionally key data classes by identity?

Kotlin有一个非常有用的特性data类,它有值语义,即编译器会根据字段的值自动生成equalshashCode .例如,你可以用像

这样的声明来表示一个抽象语法树
data class Plus(val a: Term, val b: Term) : Term()

但是当需要将抽象语法树转换为 SSA 形式时,身份突然变得很重要; a+b 不能与那次 发生混淆。

理想情况下需要的数据 类 可以在一个上下文中用值语义处理,在另一个上下文中用引用语义处理。

其中一部分可以通过使用 ===== 运算符进行值相等与身份比较来完成。图片的另一半是集合、集合和地图,它们现在有时需要根据身份而不是内容来散列它们的键。

有没有办法覆盖集合和映射中键的默认处理方式,也就是说这次使用标识而不是内容?

我的看法不是值语义与引用语义,而是关于身份。

一个数据class表示一个值。一个值是不可变的并且没有标识,这意味着当且仅当它们具有相同的内容时,两个值才相同。这就是编译器可以自动生成 equals 和 hashcode 的原因。

如果要对具有身份的实体建模,即随时间推移与一系列不同值关联的稳定逻辑实体,则应使用常规 class 并定义其身份。可以是uuid,也可以是内存地址。

也可以使用数据对实体建模 class。你可以这样定义它:

data class Plus(val id: Long, val a: Term, val b: Term) : Term()

或者更像@marstran的建议

data class Entity(val id: Long, val value: Any)

@marstran 和@gidds 解决方案很实用并且可以完成工作,但我认为您应该注意不要让您的代码混乱。在 IdentityHashMap javadoc 中甚至有这个警告:This class is not a general-purpose Map implementation!虽然此 class 实现了 Map 接口,但它故意违反了 Map 的一般契约,该契约要求在比较对象时使用 equals 方法。此 class 仅用于需要引用相等语义的极少数情况。