HashMap源码分析(jdk1.8)

本文深入分析了HashMap在JDK1.8中的实现,对比了与JDK1.6的差异,如Node内部类的变化、新增的构造方法和优化的哈希表实现。当链表长度达到8时,HashMap会将链表转换为红黑树以提高查找效率。此外,文章还探讨了HashMap的构造方法、扩容策略以及遍历和修改时的注意事项。
摘要由CSDN通过智能技术生成

HashMap源码前前后后看了好几次,也和同事分享过好几次,每次都有新的收获。

分享也是一种提高!

本文首写于个人云笔记(点击访问),经多次修改,短期内不会有重大修改了,现发于此,有任何问题欢迎交流指正。

    本文最初借鉴于http://www.cnblogs.com/hzmark/archive/2012/12/24/HashMap.html,其基于jdk1.6,自己分析jdk1.8后,发现有很大的不同,遂记录于此。

    Java最基本的数据结构有数组和链表。数组的特点是空间连续(大小固定)、寻址迅速,但是插入和删除时需要移动元素,所以查询快,增加删除慢链表恰好相反,可动态增加或减少空间以适应新增和删除元素,但查找时只能顺着一个个节点查找,所以增加删除快,查找慢。有没有一种结构综合了数组和链表的优点呢?当然有,那就是哈希表(虽说是综合优点,但实际上查找肯定没有数组快,插入删除没有链表快,一种折中的方式吧)。一般采用拉链法实现哈希表

        JDK1.6中HashMap采用的是位桶+链表的方式,即我们常说的散列链表的方式;JDK1.8中采用的是位桶+链表/红黑树的方式,也是非线程安全的。当某个位桶的链表的长度达到某个阀值的时候,这个链表就将转换成红黑树。


1、HashMap的定义

1.1 所属包:package java.util;

1.2 导入包:

import java.io.IOException;

import java.io.InvalidObjectException;

import java.io.Serializable;

import java.lang.reflect.ParameterizedType;

import java.lang.reflect.Type;

import java.util.function.BiConsumer;

import java.util.function.BiFunction;

import java.util.function.Consumer;

import java.util.function.Function;

1.3定义:

public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, CloneableSerializable {}

2、HashMap的部分属性

    private static final long serialVersionUID = 362498820763181265L;

     //The default initial capacity - MUST be a power of two.

    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; //jdk1.6直接写16,这效率更快??

     // The maximum capacity,MUST be a power of two <= 1<<30.

    static final int MAXIMUM_CAPACITY = 1 << 30; // 2的30次方

    static final float DEFAULT_LOAD_FACTOR = 0.75f; //填充比,装载因子

    /**(jdk1.8新加

     * The bin count threshold for using a tree rather than list for a

     * bin.当add一个元素到某个位桶,其链表长度达到8时将链表转换为红黑树.

     * 2< value<=8 时to mesh with assumptions in  tree removal about conversion back to plain bins upon shrinkage.

     *链表转为binCount>=TREEIFY_THRESHOLD-1,-1 for 1st。

     */ //当某个桶中的键值对数量大于8个【9个起】,且桶数量大于等于64,则将底层实现从链表转为红黑树   

       // 如果桶中的键值对达到该阀值,则检测桶数量   

    static final int TREEIFY_THRESHOLD= 8; //jdk1.8新加

     /**
     * The bin count threshold for untreeifying a (split) bin during a
     * resize operation. Should be less than TREEIFY_THRESHOLD, and at
     * most 6 to mesh with shrinkage detection under removal.
    * 仅用于 TreeNode的 final void split(HashMap<K,V> map, Node<K,V>[] tabint indexint bit) {
            if  (lc <= UNTREEIFY_THRESHOLD)  
                    //太小则转为链表   
                   tab[index] = loHead.untreeify(map); 
        }

     */

    static final int UNTREEIFY_THRESHOLD = 6; //jdk1.8新加

     /**
     * The smallest table capacity for which bins may be treeified.
     * (Otherwise the table is resized if too many nodes in a bin.)
     * Should be at least 4 * TREEIFY_THRESHOLD to avoid conflicts
     * between resizing and treeification thresholds.
     * 链表转树时,if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
            resize(); // 即不转为树了

     */  //当桶数量到达64个的时候,才可能将链表转为红黑树

    static final int MIN_TREEIFY_CAPACITY = 64; //jdk1.8新加

    /* ---------------- Fields -------------- */

    // jdk1.6 为 transient Entry[] table;

    transient Node<K,V>[] table; //存储元素(位桶)的数组,length power of two

    transient Set<Map.Entry<K,V>> entrySet;

    transient int size; // key-value对,实际容量

    transient int 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值