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