在Java中使用哈希和HashSet时,我有些疑惑。
我们知道应该满足的假设:
if elements are equals then also their hashes are equals
换句话说,:
a.equals(b) ---> a.hashCode() == b.hashCode()
但是,我们不能这样说
a.hashCode() == b.hashCode() ---> a.equals(b)
问题在于我读了包含HashSet
计算哈希h
的内容,然后只在桶中搜索哈希h
的元素。它没有为equals
的存储分元调用h
- 它只会hashCode
。这意味着我们contains
可以返回错误的答案,如果元素具有等于哈希值,但equals
返回false
(正如我上面提到的那样可能)。
答案 0 :(得分:1)
虽然确实如此
a.hashCode() == b.hashCode() doesn't mean that a.equals(b)
当调用Java HashSet中包含Method时,将调用后备HashMap的containsKey方法。此方法检查该Object的Node是否为null,getNode函数还检查该键是否等于该对象
final Node<K,V> getNode(int hash, Object key) {
Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
if ((tab = table) != null && (n = tab.length) > 0 &&
(first = tab[(n - 1) & hash]) != null) {
if (first.hash == hash && // always check first node
((k = first.key) == key || (key != null && key.equals(k))))
return first;
if ((e = first.next) != null) {
if (first instanceof TreeNode)
return ((TreeNode<K,V>)first).getTreeNode(hash, key);
do {
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
} while ((e = e.next) != null);
}
}
return null;
}
答案 1 :(得分:1)
首先,您应该了解hashmap在java中的工作原理:
java中的HashMap将key和value对象存储在bucket中,作为Entry类的对象,它实现嵌套接口Map.Entry。
当put()方法用于存储(Key,Value)对时,HashMap实现调用Key对象上的hashcode来计算用于查找将存储Entry对象的存储桶的哈希。当get()方法用于检索值时,再次使用key对象来计算哈希值,然后使用该哈希值查找存储该特定密钥的存储桶。
HashMap密钥对象用于比较,也使用equals()方法Map知道如何处理哈希冲突(哈希冲突意味着多个密钥具有相同的哈希值,因此分配给同一个桶。在这种情况下,对象存储在链表中
hashCode方法有助于找到存储该密钥的存储桶,equals方法有助于找到正确的密钥,因为在一个存储桶中可能存在多个键值对。
所以现在打电话给你的问题
我。如果元素等于,那么它们的哈希值也是等于 II。 a.equals(b)---&gt; a.hashCode()== b.hashCode() III。 a.hashCode()== b.hashCode()---&gt; a.equals(b)中
Blockquote并不总是如此,两个不等对象拥有相同的哈希码是完全合法的。它被HashMap用作“第一遍过滤器”,以便地图可以快速找到具有指定键的可能条目。如果两个不相等的对象不能具有相同的哈希码,则会将您限制为2 ^ 32个可能的对象。
现在来到HashSet
Blockquote Set是一组唯一对象,Java定义唯一性HashSet中的两个对象不相等