首页 > 解决方案 > 如果将常量返回到哈希码并且返回 false 到 equals 会发生什么

问题描述

hashcode 或 hashmap 是如何工作的,如果我们重写 hashcode,它总是返回一个常量,而重写的 equals 方法返回 false,它如何在返回或删除时识别确切的对象?time bean 忘记了所有这些东西的性能,我的问题是它如何识别确切的对象,让我再解释一下,我有一个带有两个字段的 person 类,并且覆盖了始终返回 1 的哈希码和覆盖了返回 false 的 equals 方法,创建了 3 个对象,对象 1 - id 10 名称 AAAA,对象 2 - id 20,名称 BBB,对象 3 - id 30,名称 CCC,我已将所有三个对象添加到 hashSet,之后我删除了对象2、这里如何识别它的确切对象(20、BBB)

标签: javahashmapequalshashsethashcode

解决方案


HashMap好吧,当使用/HashSet或其他使用它来优化比较/搜索的代码时,常量哈希码是有效的并且“只是”一个性能问题。

equals()然而,总是返回的实现false会破坏 equals 的约定,并会导致许多类型的集合出现问题/令人惊讶的行为。

JavaDocs 中equals

equals 方法在非空对象引用上实现等价关系:

  • 它是自反的:对于任何非空引用值 x,x.equals(x) 应该返回 true。
  • 它是对称的:对于任何非空引用值 x 和 y,当且仅当 y.equals(x) 返回 true 时,x.equals(y) 才应该返回 true。
  • 它是可传递的:对于任何非空引用值 x、y 和 z,如果 x.equals(y) 返回 true 并且 y.equals(z) 返回 true,则 x.equals(z) 应该返回 true。
  • 它是一致的:对于任何非空引用值 x 和 y,x.equals(y) 的多次调用始终返回 true 或始终返回 false,前提是没有修改对象上 equals 比较中使用的信息。
  • 对于任何非空引用值 x,x.equals(null) 应该返回 false。

一个return false实现打破了第一个要求。

JavaDocs 中hashcode

  • 如果根据 equals(java.lang.Object) 方法,如果两个对象不相等,则不需要对两个对象中的每一个调用 hashCode 方法都必须产生不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同的整数结果可能会提高哈希表的性能。

正如 @Mensur QulamiHashMap在评论中指出的那样,如果您的实现使用参考比较==来优化节点搜索,它可能仍然可以正常工作。

OpenJDK 12 HashMap.getNode(int hash, Object key)

((k = first.key) == key || (key != null && key.equals(k))))

所以这个实现在尝试之前检查引用相等equals(),但这不能保证。

JavaDocs 严格按照以下HashMap.get方式定义equals()

更正式地说,如果此映射包含从键 k 到值 v 的映射(key==null ? k==null : key.equals(k)),则此方法返回v; 否则返回null

(如果的实现equals符合上述约定,则等效,因此 OpenJDK 所做的优化是有效的)


推荐阅读