关于hashMap的key和value的理解

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];

    table[bucketIndex] = new Entry<K,V>(hash, key, value, e);  //构造方法Entry是关键

if (size++ >= threshold)

    resize(2 * table.length); 

}

     上面方法的代码很简单,但其中包含了一个设计:系统总是将新添加的 Entry 对象放入 table 数组的 bucketIndex 索引处——如果 bucketIndex 索引处已经有了一个 Entry 对象,那新添加的 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




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值