HashMap1.8源码分析1---put

本文主要讲jdk1.8中HashMap原理。

HashMap的基本结构是数组+链表+红黑树。首先分析几个静态常量:

默认初始化容量为16,1<<4采用位运算效率更高。
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

最大容量

static final int MAXIMUM_CAPACITY = 1 << 30;

默认负载因子0.75

static final float DEFAULT_LOAD_FACTOR = 0.75f;

链表转红黑树的阈值

static final int TREEIFY_THRESHOLD = 8;

红黑树转回链表的阈值

static final int UNTREEIFY_THRESHOLD = 6;

开始转红黑树的最小容量

static final int MIN_TREEIFY_CAPACITY = 64;

下面分析几个构造方法:

无参构造都是默认值。

HashMap(int initialCapacity)构造方法,指定初始化map的容量,然后调用第一个构造方法;

HashMap(int initialCapacity, float loadFactor)构造方法,传入容量和加载因子,threshold属性代表初始化数组时的长度。

这里当传入initialCapacity时,会调用tableSizeFor()方法:

该方法对传入的值先-1,是为了避免传入值正好是2的幂,分析方法是对n进行右移位然后按位或运算

综上,这个方法正如注释所言,是为了得到大于传入值的最近的2的幂。

下面分析put方法:

public V put(K key, V value) { return putVal(hash(key), key, value, false, true); }

里面先是调用的hash(key)方法:

static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }

这里获得key.hashCode()的值,并将其高16位与低16位做按位异或运算,目的是为了降低hash碰撞的概率。然后返回一个int值。

然后分析putVal的具体流程,首先判断tab数组是否为初始数组,第一次put则调用resize()方法。

根据初始化HasMap的参数得到threshold的值,然后初始化了一个数组。默认是16,继续分析putVal过程,

p = tab[i = (n - 1) & hash]中(n-1)&hash会得到一个介于0~n-1的值,这个值就是数组的下标。

然后继续判断,当前传入的e是否是第一个节点(hash,key都相同),如果是就替换,否则就判断是否是树(红黑树后面章节单独讲),否则就是一个链表,然后循环这个链表,如果p.next是null,就新增Node,否则就去比较是否和传入值的hash,key相等,相等则替换,跳出循环,否则就继续循环直到新增节点,此时要判断链表长度是否超过阈值8,超过则转换成红黑树。

当数组分布到达threshold,首次默认12时,开始扩容(后面章节单独讲)

至此,put流程基本完成.

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值