refer to: http://xiaolu123456.iteye.com/blog/1485349
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))) {/
/当key的hash值相同,且内容相等(equal)时,覆盖原来位置,
这是map接口的要求
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
上面程序中用到了一个重要的内部接口:Map.Entry,每个 Map.Entry 其实就是一个 key-value 对。从上面程序中可以看出:当系统决定存储 HashMap 中的 key-value 对时,完全没有考虑 Entry 中的 value,仅仅只是根据 key 来计算并决定每个 Entry 的存储位置。这也说明了前面的结论:我们完全可以把 Map 集合中的 value 当成 key 的附属,当系统决定了 key 的存储位置之后,value 随之保存在那里即可.HashMap程序经过我改造,我故意的构造出了hash冲突现象,因为HashMap的初始大小16,但是我在hashmap里面放了超过16个元素,并且我屏蔽了它的resize()方法。不让它去扩容。这时HashMap的底层数组Entry[] table结构如下:
Hashmap里面的bucket出现了单链表的形式,散列表要解决的一个问题就是散列值的冲突问题,通常是两种方法:链表法和开放地址法。链表法就是将相同hash值的对象组织成一个链表放在hash值对应的槽位;开放地址法是通过一个探测算法,当某个槽位已经被占据的情况下继续查找下一个可以使用的槽位。java.util.HashMap采用的链表法的方式,链表是单向链表。形成单链表的核心代码如下:
void addEntry(int hash, K key, V value, int bucketIndex) {
Entry<K,V> e = table[bucketIndex];
new Entry<K,V>(hash, key, value, e); //构造方法Entry是关键
if (size++ >= threshold)
2 * table.length);
}
那新添加的 Entry 对象指向原有的 Entry 对象(产生一个 Entry 链),如果 bucketIndex 索引处没有 Entry 对象,也就是上面程序代码的 e 变量是 null,也就是新放入的 Entry 对象指向 null,也就是没有产生 Entry 链。
测试:
import java.util.HashMap;
import java.util.Map;
class mykey {
String str=null;
public mykey(String a){
str=a;
}
@Override
public int hashCode() {
return 1;
}
@Override
public boolean equals(Object obj) {
return false;
}
}
public class MyMap {
public static void main(String[] args) {
Map m=new HashMap();
mykey k1=new mykey("A");
mykey k2=new mykey("B");
m.put(k1, "jimmy");
m.put(k2,"kaka");
// m.put("1", "deco");
//m.remove("1");
System.out.println(k1.hashCode());
System.out.println(k2.hashCode());
System.out.println(m.get(k2));
System.out.println(m.size());
}
}输出:故意让hashcode相等,equals不等,这时会映射到同一个bucket上,entry形成一个链
1 :hashode
1 : hashcode
kaka
2