HashMap 实现原理和底层结构

1. 什么是哈希表?
哈希表也叫散列表(Hash table),是根据关键码值(key value)而直接进行访问的数据结构,也就是说,他通过把关键码值映射到表中的一个位置来访问记录,来加快查找速度.这个映射函数叫散列函数,存放记录的数组叫散列函数或哈希表
2. HashMap 的实现原理
HashMap 的主干是一个Entry 数组.Entry 是HashMap 的基本单元,每一个Entry包含一个key-value键值对
Entry 是HashMap 的一个静态内部类
简单来说,HashMap是由数组+链表组成的,数组是HashMap的主体,链表则是为了解决哈希冲突而存在的,如果定位到的数组不含链表(entry的next 为null),那么查找和添加操作都很快,仅需一次寻址即可,如果定位到的数组含有链表,对于添加操作,时间复杂度是O(1),因为最新的entry 会插入在链表头部,只需要简单改变引用链即可,但是对于查询操作,会比较复杂,此时需要遍历链表,然后通过key对象的equals 方法一个个的比对查找,所以从性能考虑,HashMap 中出现的链表越少越好
3. HashMap 为什么线程不安全?
(1) 我们知道HashMap 的底层是一个Entry数组,一旦发生Hash冲突的时候,我们采用拉链法解决Hash冲突,多线程情况向,当出现两个以上Hash冲突时,两个元素都会往链表的头结点插入数据(在put 元素的时候,put()方法的addEntry()方法为同步,),势必会造成一个元素被另外一个元素覆盖
(2) 我们知道当HashMap发生Hash冲突,并且size大于阀值的时候,HashMap 会调用resize()方法,儿resize()方法是没有同步的,多线程环境下,当一个线程完成部分赋值的时候,CPU 时间片被另外一个线程获取,而这个线程会在刚刚的那个数组table基础上进行扩容,这样也会出现线程安全问题
4. HashMap 参数
构造器:
new HashMap(): 构造一个初始容量为16,负载因子为0.75的HashMap
new HashMap(int initialCapacity): 构造一个初始容量为initialCapacity,负载因子为0.75的HashMap
new HashMap(int initialCapacity,float loadFactor): 构造一个初始容量为initialCapacity,负载因子为loadFactor的HashMap
initialCapacity: HashMap 底层数组的长度,既为底层数组的最大长度
loadFactor: 负载因子loadFactor定义为:散列表的实际元素数目(n)/ 散列表的容量(m); 负载因子是衡量一个散列表的空间使用程度, 负载因子大,空间利用率高,数据查找慢,反之数据查找快
modCount: HashMap修改次数,我们知道HashMap 是线程不安全的,我们对HashMap 的修改都将增加这个值,在迭代器初始化过程中我们会将modCount赋值给exceptModCount,在迭代过程中,我们会判断modCount和exceptModCount是否相等,如果不相等,表示其他线程修改了HashMap(modCount 的修饰符是volatile,保证了变量线程之间的可见性)
常用: Hashmap 不保证元素的顺序,允许null键null值,元素不重复

HashMap java8新特性
HashMap 底层数据加入红黑树
当同一个hash 值下的链表不小于8的时候,将会把链表转换为红黑树存储

猜你喜欢

转载自blog.csdn.net/weixin_42118323/article/details/88355954