JAVA HashMap是怎么解决冲突的?
1.Java 1.6源代码的HashMap,get数据或者put数据的时候,会产生冲突吗?
2.如果产生了冲突,是如何解决的?使用的开放地址法?链地址法?或者其他?
为了方便说明,我假定现在已经有一个Map myMap = new HashMap(),一个有6条数据,其中第2个位置上面有3个数据,如图:
附上HashMap的源码:
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
开始问问题了:
1.现在如果我想添加一个元素Key1-Value1,计算出来的hashCode是2,那现在这个元素放到哪里呢?放到元素B的下面?HashMap的源码里面是怎么实现这个的呢?
2.addEntry(hash, key, value, i);是什么意思呢?什么时候会用到呢?
下面是get方法:
public V get(Object key) {
if (key == null)
return getForNullKey();
int hash = hash(key.hashCode());
for (Entry<K,V> e = table[indexFor(hash, table.length)];
e != null;
e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
return e.value;
}
return null;
}
3.如果myMap.get(2),我现在想要的是B元素,HashMap里面是怎么处理的呢?e.next是循环整个map还是只循环key=2的这个链表呢?
请高手耐心解答。。。不胜感激。。。
如果有描述不清楚的,请指教
------解决方案--------------------总体上是链地址法,先执行hash,再执行equals。
处理冲突倒不是很复杂,无非是遍历一个链表,最后调用“头插法”,比较精髓的是这个函数:
static int hash(int h) {
// This function ensures that hashCodes that differ only by
// constant multiples at each bit position have a bounded
// number of collisions (approximately 8 at default load factor).
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
还有这个函数:
static int indexFor(int h, int length) {
return h & (length-1);
}
纯位运算的内容,参考: http://zhangshixi.iteye.com/blog/672697