当向hashMap添加键值对时,为什么Java会生成hashMap';什么是哈希代码更改?
如果查看hashMap中java的hashCode方法,您会发现:当向hashMap添加键值对时,为什么Java会生成hashMap';什么是哈希代码更改?,java,hash,hashmap,hashcode,hashset,Java,Hash,Hashmap,Hashcode,Hashset,如果查看hashMap中java的hashCode方法,您会发现: public int hashCode() { int h = 0; Iterator<Entry<K,V>> i = entrySet().iterator(); while (i.hasNext()) h += i.next().hashCode(); return h; } 那里的高兰蒂人可能会发生碰撞。还有其他Map实现,包括和,它们不显示您描述的
public int hashCode() {
int h = 0;
Iterator<Entry<K,V>> i = entrySet().iterator();
while (i.hasNext())
h += i.next().hashCode();
return h;
}
那里的高兰蒂人可能会发生碰撞。还有其他Map
实现,包括和,它们不显示您描述的行为。在LinkedHashMap
的情况下,Javadoc(部分)将其描述为Map
接口的哈希表和链表实现,具有可预测的迭代顺序
为什么Java允许这样的行为
因为根据键的equals()
实现,键应该是不变的。如果对键进行变异,从而影响通过其equals()
方法进行的比较,则映射的行为未指定
这正是当您更改HashMap
而它是HashSet
的一个元素时所做的,因为HashSet
实际上是由HashMap
支持的
这是一个节选的:
注意:如果将可变对象用作贴图键,则必须非常小心。如果对象是贴图中的关键点时,对象的值以影响相等比较的方式更改,则不会指定贴图的行为。这项禁令的一个特例是,不允许地图本身包含密钥。虽然允许映射将自身包含为一个值,但还是要特别小心:equals和hashCode方法在这样的映射上不再得到很好的定义
如果我是你,我不会使用可变映射作为依赖于其元素不可变性的结构的键。你想知道为什么,还是想知道如何解决这个问题?我想知道为什么HashMap的哈希代码依赖于其存储的数据。
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
public class Main {
public static void main(String[] args) {
HashSet<HashMap<Integer, String>> set = new HashSet<>();
HashMap<Integer, String> b = new HashMap<>();
System.out.println("adding hashcode: " + b.hashCode() + "to set");
set.add(b);
b.put(8, "arsenal");
for(HashMap<Integer, String> map: set){
Iterator it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry)it.next();
System.out.println(pair.getKey() + " = " + pair.getValue());
}
}
System.out.println("Finding b: " + set.contains(b));
System.out.println(b.hashCode());
set.add(b);
for(HashMap<Integer, String> map: set){
Iterator it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry)it.next();
System.out.println(pair.getKey() + " = " + pair.getValue());
}
}
}
}