应该 hashCode() return 一个对象的唯一 ID
Should hashCode() return an object's unique ID
在我的 Kotlin/Java 项目中,我编写了一些继承抽象 class BaseItem
:
的模型 classes
/**
* All data model classes should implement this
*/
abstract class BaseItem {
/**
* A unique integer identifier used to represent the data item in the database.
*/
abstract val id: Int
override fun equals(other: Any?) = (other is BaseItem) && id == other.id
}
这些模型 classes 将用于表示数据库中的数据。在数据库中,有一个包含唯一整数标识符的 ID 列。
所以当我使用模型classes时,保证每个id
属性都是唯一的。
读完 hashCode()
的 Java 规格:
- Whenever it is invoked on the same object more than once during an execution of an application, the
hashCode
method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
- If two objects are equal according to the
equals(Object)
method, then calling the hashCode
method on each of the two objects must produce the same integer result.
- It is not required that if two objects are unequal according to the
equals(Object)
method, then calling the hashCode
method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.
我的问题是:
在 hashCode()
中 return 这个唯一标识符是好的做法吗?
注意:我知道在 Kotlin 中,我们可以使用 data
classes 以便编译器自动派生预定义成员,如 equals()
、hashCode()
、toString()
,等等,但是 abstract
classes 不能是 data
classes。 (但是,我可以制作 BaseItem
data
classes 的 subclasses - 我不确定这是否是这个用例的更好选择) .
因为你的摘要 BaseClass
是针对数据 classes (a.k.a.value classes) 它应该定义 equals
和 hashCode
作为 abstract
并强制执行具体的 classes 来执行它们。例如:
abstract class BaseItem {
abstract val id: Int
abstract override fun equals(other: Any?): Boolean
abstract override fun hashCode(): Int
}
data class Person(override val id: Int, val name: String) : BaseItem()
data class Product(
override val id: Int,
val name: String,
val cost: BigDecimal
) : BaseItem()
在基础 class 中实现这些功能而不在具体的子 class 中覆盖它们可能会导致违反 equals
& hashCode
合同。
如果您不强制子classes 实现equals
/hashCode
:
,这里有一个对称破坏的例子
abstract class BaseItem {
abstract val id: Int
override fun equals(other: Any?) = (other is BaseItem) && id == other.id
override fun hashCode() = id
}
class Person(override val id: Int, val name: String) : BaseItem() {
override fun equals(other: Any?): Boolean {
return (other is Person) && id == other.id && name == other.name
}
override fun hashCode() = 31 * (31 + id.hashCode()) + name.hashCode()
}
class Product(
override val id: Int,
val name: String,
val cost: BigDecimal
) : BaseItem()
fun main(args: Array<String>) {
val baseItem1: BaseItem = Person(1, "Oliver")
val baseItem2: BaseItem = Product(1, "grease", BigDecimal.TEN)
println(baseItem1 == baseItem2) // false
println(baseItem2 == baseItem1) // true
}
如果 equals
/hashCode
是根据他们的合同实施的,那么两个相等性检查总是 return 相同的结果(true
或 false
,在这种情况下,它应该是 false
,因为 Product
也应该覆盖这些函数并检查 other
是否也是 Product
并检查每个相关的 属性,等等。 ).
参见 Joshua Bloch 的 Effective Java 第二版 中的 "Item 8: Obey the general contract when overriding equals" 和 "Item 9: Always override hashCode when you override equals",了解有关这些合同和周围问题的更多详细信息分层价值的不同方法 classes.
在我的 Kotlin/Java 项目中,我编写了一些继承抽象 class BaseItem
:
/**
* All data model classes should implement this
*/
abstract class BaseItem {
/**
* A unique integer identifier used to represent the data item in the database.
*/
abstract val id: Int
override fun equals(other: Any?) = (other is BaseItem) && id == other.id
}
这些模型 classes 将用于表示数据库中的数据。在数据库中,有一个包含唯一整数标识符的 ID 列。
所以当我使用模型classes时,保证每个id
属性都是唯一的。
读完 hashCode()
的 Java 规格:
- Whenever it is invoked on the same object more than once during an execution of an application, the
hashCode
method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.- If two objects are equal according to the
equals(Object)
method, then calling thehashCode
method on each of the two objects must produce the same integer result.- It is not required that if two objects are unequal according to the
equals(Object)
method, then calling thehashCode
method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.
我的问题是:
在 hashCode()
中 return 这个唯一标识符是好的做法吗?
注意:我知道在 Kotlin 中,我们可以使用 data
classes 以便编译器自动派生预定义成员,如 equals()
、hashCode()
、toString()
,等等,但是 abstract
classes 不能是 data
classes。 (但是,我可以制作 BaseItem
data
classes 的 subclasses - 我不确定这是否是这个用例的更好选择) .
因为你的摘要 BaseClass
是针对数据 classes (a.k.a.value classes) 它应该定义 equals
和 hashCode
作为 abstract
并强制执行具体的 classes 来执行它们。例如:
abstract class BaseItem {
abstract val id: Int
abstract override fun equals(other: Any?): Boolean
abstract override fun hashCode(): Int
}
data class Person(override val id: Int, val name: String) : BaseItem()
data class Product(
override val id: Int,
val name: String,
val cost: BigDecimal
) : BaseItem()
在基础 class 中实现这些功能而不在具体的子 class 中覆盖它们可能会导致违反 equals
& hashCode
合同。
如果您不强制子classes 实现equals
/hashCode
:
abstract class BaseItem {
abstract val id: Int
override fun equals(other: Any?) = (other is BaseItem) && id == other.id
override fun hashCode() = id
}
class Person(override val id: Int, val name: String) : BaseItem() {
override fun equals(other: Any?): Boolean {
return (other is Person) && id == other.id && name == other.name
}
override fun hashCode() = 31 * (31 + id.hashCode()) + name.hashCode()
}
class Product(
override val id: Int,
val name: String,
val cost: BigDecimal
) : BaseItem()
fun main(args: Array<String>) {
val baseItem1: BaseItem = Person(1, "Oliver")
val baseItem2: BaseItem = Product(1, "grease", BigDecimal.TEN)
println(baseItem1 == baseItem2) // false
println(baseItem2 == baseItem1) // true
}
如果 equals
/hashCode
是根据他们的合同实施的,那么两个相等性检查总是 return 相同的结果(true
或 false
,在这种情况下,它应该是 false
,因为 Product
也应该覆盖这些函数并检查 other
是否也是 Product
并检查每个相关的 属性,等等。 ).
参见 Joshua Bloch 的 Effective Java 第二版 中的 "Item 8: Obey the general contract when overriding equals" 和 "Item 9: Always override hashCode when you override equals",了解有关这些合同和周围问题的更多详细信息分层价值的不同方法 classes.