HashMap构造方法源码简读(JDK1.8)

HashMap的构造方法

//默认负载因子值
static final float DEFAULT_LOAD_FACTOR = 0.75f;
//HashMap最大容量:2的30次方
static final int MAXIMUM_CAPACITY = 1 << 30;
//当前HashMap所能容纳的键值对的最大值,超过就会进行扩容
int threshold;
//负载因子
final float loadFactor;

//构造方法一,常用的构造方法,调用会把负载因子设置为默认值0.75
public HashMap() {
        this.loadFactor = DEFAULT_LOAD_FACTOR;
    }
    
//构造方法二,这里会传入一个初始容量值,然后调用构造方法三   
public HashMap(int initialCapacity) {
        this(initialCapacity, DEFAULT_LOAD_FACTOR);
    }
    
//构造方法三   
public HashMap(int initialCapacity, float loadFactor) {
       //如果初始容量设置成小于0,则抛出IllegalArgumentException异常
       if (initialCapacity < 0)
           throw new IllegalArgumentException("Illegal initial capacity: " +
                                               initialCapacity);
       //如果设置的初始值比默认的最大容量值还大                                       
       if (initialCapacity > MAXIMUM_CAPACITY)
           //就强行赋值成默认的最大容量值:2的30次方
           initialCapacity = MAXIMUM_CAPACITY;
       //判断loadFactor变量值的合法性,不符合要求则抛出IllegalArgumentException异常
       if (loadFactor <= 0 || Float.isNaN(loadFactor))
           throw new IllegalArgumentException("Illegal load factor: " +
                                               loadFactor);
       //赋值loadFactor                                      
       this.loadFactor = loadFactor;
       //返回一个个大于或等于initialCapacity的最小2的幂值,并赋值
       this.threshold = tableSizeFor(initialCapacity);
   }
   
//构造方法四,入参是一个Map类型      
public HashMap(Map<? extends K, ? extends V> m) {
       this.loadFactor = DEFAULT_LOAD_FACTOR;
       //将传入参数m的所有元素存入本HashMap对象实例中
       putMapEntries(m, false);
   }  

//这个方法就是为了返回一个大于或等于cap的最小2的幂值,比如cap=15,就返回16,如果cap=17,就返回32
static final int tableSizeFor(int cap) {
        int n = cap - 1;
        n |= n >>> 1;
        n |= n >>> 2;
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16;
        return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
    } 
    
 //将传入参数m的所有元素存入本HashMap对象实例中的操作    
 final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {
        //获取m的长度
        int s = m.size();
        //如果长度大于0,说明m里有元素,则将m里的元素放入到本HashMap对象实例中
        if (s > 0) {
            //如果table是null,说明本HashMap对象实例里还没任何元素,因为table值的初始化是在HashMap做put操作时
            if (table == null) {
                //得出了本HashMap要存在m中的元素所需的最小容量,这里加一是怕算出小数,所以向上取整
                float ft = ((float)s / loadFactor) + 1.0F;
                //对最小容量ft做判断,小于最大容量则赋值ft值给t,否则就取最大容量值2的30次方
                int t = ((ft < (float)MAXIMUM_CAPACITY) ?
                         (int)ft : MAXIMUM_CAPACITY);
                //如果容量t的值比threshold大         
                if (t > threshold)
                    //找出比t大的最小2次幂值,赋值给threshold,作为本HashMap的容量
                    threshold = tableSizeFor(t);
            }
            //如果table不等于null,说明里面已经有元素了,那就要判断m集合里的元素个数是否大于threshold,超过了就要进行扩容
            else if (s > threshold)
                //扩容方法
                resize();
            //遍历m集合,存放进本HashMap中    
            for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
                K key = e.getKey();
                V value = e.getValue();
                putVal(hash(key), key, value, false, evict);
            }
        }
    }    
发布了178 篇原创文章 · 获赞 180 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_38106322/article/details/104347610