HashMap

1.非线程安全,可null键null值
2.无参构造默认大小16数组,负载因子0.75,扩容边界值16*0.75(阈值)
3.有参的构造函数,默认数组大小为大于或等于参数的最小的2的次幂,是为了元素分布均匀,数组每次扩容都是2倍扩容

int capacity = 1;  
while (capacity < initialCapacity)  
    capacity <<= 1;  

4.indexfor函数,对数组索引的判断。在length为2的次幂时,可以使h按位与length-1时,哈希碰撞减少,从而减少查询时的链表遍历,提高查询效率。

static int indexFor(int h, int length) {  
    return h & (length-1);  
} 

5.扩容时要进行旧数组元素复制到新的2倍长度的新数组中,产生性能消耗,所以尽量设置默认大小,并且该大小要考虑负载因子。
6.遍历思路
第一个是获取keySet,遍历keySet针对每个key获取value
第二个是获取entrySet,遍历entrySet获取每个key和value
7.put过程

public V put(K key, V value) {  
        // 如果key为null使用putForNullKey来获取  
        if (key == null)  
            return putForNullKey(value);  
        // 使用hash函数预处理hashCode  
        int hash = hash(key.hashCode());  
        // 获取对应的索引  
        int i = indexFor(hash, table.length);  
        // 得到对应的hash值的桶,如果这个桶不是,就通过next获取下一个桶  
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {  
            Object k;  
            // 如果hash相同并且key相同  
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {  
                // 获取当前的value  
                V oldValue = e.value;  
                // 将要存储的value存进去  
                e.value = value;  
                e.recordAccess(this);  
                // 返回旧的value  
                return oldValue;  
            }  
        }  

        modCount++;  
        addEntry(hash, key, value, i);  
        return null;  
    }  

8.addEntry

void addEntry(int hash, K key, V value, int bucketIndex) {  
    // 保存对应table的值  
    Entry<K,V> e = table[bucketIndex];  
        // 然后用新的桶套住旧的桶,链表  
        table[bucketIndex] = new Entry<K,V>(hash, key, value, e);  
        // 如果当前size大于等于阈值  
        if (size++ >= threshold)  
            // 调整容量  
            resize(2 * table.length);  
    }  

9.resize

void resize(int newCapacity) {  
        // 保存oldTable  
        Entry[] oldTable = table;  
        // 保存旧的容量  
        int oldCapacity = oldTable.length;  
        // 如果旧的容量已经是系统默认最大容量了,那么将阈值设置成整形的最大值,退出  
        if (oldCapacity == MAXIMUM_CAPACITY) {  
            threshold = Integer.MAX_VALUE;  
            return;  
        }  

        // 根据新的容量新建一个table  
        Entry[] newTable = new Entry[newCapacity];  
        // 将table转换成newTable  
        transfer(newTable);  
        // 将table设置newTable  
        table = newTable;  
        // 设置阈值  
        threshold = (int)(newCapacity * loadFactor);  
    }  

10.transfer

void transfer(Entry[] newTable) {  
        // 得到旧的table  
        Entry[] src = table;  
        // 得到新的容量  
        int newCapacity = newTable.length;  
        for (int j = 0; j < src.length; j++) {  
            Entry<K,V> e = src[j];  
            // 如果e不为空  
            if (e != null) {  
                src[j] = null;  
                do {  
                    Entry<K,V> next = e.next;  
                    int i = indexFor(e.hash, newCapacity); 
                    e.next = newTable[i];  
                    newTable[i] = e;  
                    e = next;  
                } while (e != null);  
            }  
        }  
    }  

参考:http://blog.youkuaiyun.com/chenssy/article/details/18323767

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值