HashMap
原理
底层使用哈希表(数组+链表),当链表过长将被转化成红黑树以实现O(logn)时间复杂度的查找
特点
键不可重复,值可以重复
底层哈希表
线程不安全
允许key为null,value也可以为null(插入时,若key为null,将value存入table[0]处)
成员变量
DEFAULT_INITIAL_CAPACITY=16
put方法过程
1、对key的hashCode再求hash值,然后计算下标
2、如果没有碰撞,直接放入桶中
3、如果碰撞了,以链表的方式来链接在后面
4、如果链表长度超过阈值(TREEIFY_THRESHOLD = 8),链表转成红黑树
5、如果节点已经存在就替换值
6、如果桶满了(容量*加载因子),就需要resize()
hash函数实现
1、高16bit不变,低16位和高16bit异或
2、(n-1)& hash得到下标
其它实现方式??
扩容机制
何时扩容
当向容器添加元素的时候,元素个数size++大于等于阈值threshold—<br>即当前数组的长度乘以加载因子的值的时候(int)(capacity * loadFactor),就要自动扩容啦。
扩容方法
resize(int newCapacity)
判断扩容前容量大小
初始化新Entry数组
通过transfer(newTable)方法将原来数组里的元素拷贝到新数组里
JDK1.7:使用大数组替换小数组,遍历旧数组,从新计算每个元素在新数组中的位置
多线程同时操作链表指针时可能出现死循环
JDK1.8:看原来的hash值新增的那个bit是1还是0就好了
新位置只可能在两个位置:原下标位置;《原下标+原容量》的位置
更新table,修改阈值