java – HashSet如何处理hashCode()?

前端之家收集整理的这篇文章主要介绍了java – HashSet如何处理hashCode()?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图更深入地理解 java.util.Collection和java.util.Map,但我对HashSet功能有一些疑问:

在文档中,它说:这个类实现了Set接口,由一个哈希表(实际上是一个HashMap实例)支持.好的,所以我可以看到HashSet总是在后台运行Hashtable.哈希表是一种结构,每次要向其添加新元素时都会请求键和值.然后,基于密钥hashCode将值和密钥存储在桶中.如果两个键的哈希码相同,则使用链表将两个键值添加到同一个桶中.如果我说错了,请纠正我.

所以,我的问题是:如果一个HashSet总是有Hashtable在后台运行,那么每次我们使用HashSet.add()方法向HashSet添加一个新元素时,HashSet应该将它添加到它的内部Hashtable.但是,Hashtable要求输入值和密钥,那么它使用什么密钥?它是否仅使用我们尝试添加的值作为键,然后使用其hashCode?如果我对HashSet实现说错了,请纠正我.

我的另一个问题是:一般来说,哪些类可以使用java对象的hashCode()方法?我问这个是因为,在文档中,它说我们每次覆盖equals()方法时都需要覆盖hashCode()方法.好吧,这真的很有道理,但我怀疑的是,如果只是建议我们应该做的就是保持一切“美好而完美”(以这种方式),或者如果真的有必要,因为可能有很多Java默认类会不断使用对象的hashCode()方法.在我的视野中,我看不到使用此方法的其他类而不是与集合相关的类.非常感谢你们

解决方法

如果你看看HashSet的实际javacode,你可以看到它的作用:
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
...

 public boolean add(E e) {
    return map.put(e,PRESENT)==null;
}

因此,您要添加的元素是支持hashmap中的Key,其值为虚拟值. hashSet实际上从未使用过这个虚拟值.

关于覆盖equals和hashcode的第二个问题:

如果要覆盖其中任何一个,则必须始终覆盖两者.这是因为hashCode的契约表明相等的对象必须具有相同的哈希码. hashcode的默认实现将为每个实例提供不同的值.

因此,如果您重写equals()但不重写hashcode()这可能会发生

object1.equals(object2) //true

MySet.add(object1);

MySet.contains(object2); //false but should be true if we overrode hashcode()

由于contains将使用哈希码来查找要搜索的存储桶,因此我们可能会获得不同的存储桶而不会找到相等的对象.

猜你在找的Java相关文章