从零开始的 HashMap 源码阅读(二) 构造函数分析

0.构造函数源码

	
     public HashMap(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: " +
                                               initialCapacity);
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal load factor: " +
                                               loadFactor);
        this.loadFactor = loadFactor;
        this.threshold = tableSizeFor(initialCapacity);
    }
    
    public HashMap(int initialCapacity) {
        this(initialCapacity, DEFAULT_LOAD_FACTOR);
    }
    
    public HashMap() {
        this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
    }
    
    public HashMap(Map<? extends K, ? extends V> m) {
        this.loadFactor = DEFAULT_LOAD_FACTOR;
        putMapEntries(m, false);
    }

第一个给的信息多就看第一个构造函数吧

 public HashMap(int initialCapacity, float loadFactor) {
 	//一些校验
 	//如果传入容量小于零 
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: " +
                                               initialCapacity);
       //如果传入容量大于规定最大值就修改成最大值
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
        //如果负载因子不合法抛出异常
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal load factor: " +
                                               loadFactor);
        this.loadFactor = loadFactor;
        //因为table的初始化长度必须是2的次方数,所以要先将不规则的initialCapcity通过 tableSizeFor 转化成2的次方数再乘以负载因子返回给threshold
        this.threshold = tableSizeFor(initialCapacity);
    }

前面的都是一些判断,判断传入参数是否合法
主要是最下面的 tableSizeFor函数,我们传入的cap可能是不规则的,通过tableSizeFor就可以返回最接近cap的2的次方数0.
为什么table.length一定要是2的次方数呢?
因为节点插入到数组的下标是
index = hashcode&table.length-1,HashMap为了减少碰撞,就要将数据分配均匀.hashcode&table.length-1能正常工作的前提就是table.length是2的次方数
为什么这样能均匀分布减少碰撞呢?2的n次方实际就是1后面n个0,2的n次方-1 实际就是n个1;
例如长度为9时候,3&(9-1)=0 2&(9-1)=0 ,都在0上,碰撞了;
例如长度为8时候,3&(8-1)=3 2&(8-1)=2 ,不同位置上,不碰撞;

1.tableSizeFor分析

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

传入给定的一个容量,通过一顿位运算操作返回成该数最近的较大的2的次方数

如何工作的?
比如传入的cap为10

cap == 10
n = 10-1=9 == 1001
1001 | 0100 ⇒ 1101
1101 | 0011 ⇒ 1111
1111 | 0000 ⇒ 1111
1111 ⇒ 15

return 15+1

最后返回了16

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值