HashMap
发展历程
hashmap最早出现在jdk1.2,一直到jdk1.7hashmap都没有大的改变,在1.7之前底层数据存储结构是数组+链表;基于这样的存储结构,他增删数据速度快,但是由于数据的越来越多,查询数据的效率变低,所以基于这个原因,hashmap在jdk1.8版本中做了极大的优化,将数据存储结构变为数组+链表+红黑树
jdk
hashmap继承自abstractmap抽象类,实现了cloneable和serializable接口
key,value键值对接收null值,value可以有多个空值,但是key只能有一个null值
hashmap没有用Syschronized关键字修饰,所以非线程同步,当需要做线程安全的操作时可以改用ConcurrentHashMap
初始化hashmap和增加数据
hashmap的初始化大小是16,而且其初始容量规定必须是2的 幂次方大小 。
初始化HashMap可以通过四种构造函数进行初始化
一个是无参构造方法public HashMap()
加上三个有参构造方法
public HashMap(int initialCapacity)
public HashMap(Map<? extends K, ? extends V> m)
public HashMap(int initialCapacity, float loadFactor)
通过put方法进行数据的增加
1、首先put方法传入键值对
2、根据键计算hash
3、根据哈希算法计算相应的值在数组中存放的位置
4、判断当前位置是否已有相应的值,
如果没有,则直接存放在数组中,
如果有,那么这个位置就有了冲突,称为hash冲突;
5、那么此时再判断此时的数据结构是什么,
如果是红黑树,则直接插入进红黑树;
如果是链表,那么需要再进行一次判断
6、判断链表长度是否大于8,
如果不大于8,则直接存放在链表里面;
如果大于8,则需要将数据结构调整为红黑树,然后再将数据存入红黑树中。
扩容机制
当put太多数据,会造成当前容量不足以存放目前的数据,所以就需要进行扩容。
首先会一旦判断当前容量不足,则会扩容一个2倍新建数组;
然后把相应的旧数组移到新数组中
然后把新数组引用到hashmap的table中
然后重新设置阈值即可