HashMap 源码

对于JDK 1.7 来说,HashMap的结果就是 数组+链式 的结构;

具体来说:对于put方法:

   public V put(K key, V value) {
        if (table == EMPTY_TABLE) { //首次开始的时候,Entry<K,V>[] 为空
            inflateTable(threshold);  //初始化HashMap的Entry<K,V>[] 数组,默认容量(threshold= capacity * loadFactor)是16;
        }
        if (key == null)
            return putForNullKey(value); //保存key为null 的键值对-->1
        int hash = hash(key);                 //获取key的hash值-->3
        int i = indexFor(hash, table.length); //hash值与Entry[]的长度做&运算结果作为元素落在Entry[]上的下标
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {  //找到下标所在的元素Entry,遍历Entry的链后面的元素next
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { //如果存在相同的key就替换掉,并返回就value
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }
        modCount++;
        addEntry(hash, key, value, i);  //当该下标不曾被暂用,不存在元素是,就直接去新增Entry下标为i的元素
        return null;

    } 

--->1:

    private V putForNullKey(V value) {
        for (Entry<K,V> e = table[0]; e != null; e = e.next) {  //对于key为null的情况,默认遍历第一个数组及下面的链;
            if (e.key == null) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }
        modCount++;    
        addEntry(0, null, value, 0);  -->2 增加Entery[]的元素
        return null;
    }

-->2:

    void addEntry(int hash, K key, V value, int bucketIndex) {  //
        if ((size >= threshold) && (null != table[bucketIndex])) { //判断是否大于容量值threshold 
            resize(2 * table.length);                          //如果大于扩展容量是原来的2倍
            hash = (null != key) ? hash(key) : 0;       //获取key的hash值,key为null的hash是0
            bucketIndex = indexFor(hash, table.length);  //得到元素在Entry[]数组中的位置下标
        }
        createEntry(hash, key, value, bucketIndex);  //对于key为null直接创建元素,在这创建了
    }

-->3:

    final int hash(Object k) {
        int h = hashSeed;
        if (0 != h && k instanceof String) {
            return sun.misc.Hashing.stringHash32((String) k);
        }
        h ^= k.hashCode();
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);

    }


对于get方法:

     public V get(Object key) {
        if (key == null)
            return getForNullKey();  //对于key是null的情况,直接取Entry[0]位置的元素(JDK1.7)
        Entry<K,V> entry = getEntry(key);   --->4
        return null == entry ? null : entry.getValue();  //直接返回
    }

 

--->4:

   final Entry<K,V> getEntry(Object key) { 

        if (size == 0) {
            return null;
        }

        int hash = (key == null) ? 0 : hash(key);   //获取key的hash值

        //获取hash对应的下标,并找出下标对应的元素,然后遍历Entry节点所在的链,直至找到hash相等且equal的元素并返回e

        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 != null && key.equals(k))))
                return e;
          }
        return null;
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值