目录
HashMap 的 table 的容量如何确定?loadFactor 是什么? 该容量如何变化?这种变化会带来什么问题?
(4)JDK1.8 中 HashMap 的 put(),get() 方法具体的一个执行流程
2.LinkedHashMap/TreeMap/HashTable
本文简单介绍双列集合的概念知识点,后面会出关于集合源码的详细解析
一、Map
Map集合是一种以键值对形式存储和操作数据的数据结构,建立了key-value之间的映射关系,key不允许重复,value可以重复。Map常用实现类有HashMap,TreeMap,LinkedHashMap和Hashtable。
双列集合结构图:
二、实现类
1.HashMap
(1)基本概念:
HashMap底层基于哈希表算法,HashMap中存储的key对象的hashCode值决定了 在哈希表中的存储位置,因为HashMap中的key是Set,所以不能保证添加的先后顺序,也不允许重复。
哈希码的介绍:哈希码的主要作用是在集合中进行元素的快速查找。它通过哈希函数将键转换为一个唯一的整数,决定了键值对在数组中的存储位置。如果两个键的哈希码不同,它们会被分配到不同的桶中,提高了查找效率。如果哈希码相同,就会发生哈希冲突,需要进一步处理。
(2)HashMap的底层数据结构:
1.7和1.8有哪些区别?
底层实现:
- 在JDK8中,HashMap底层是采用“数组+链表+红黑树”来实现的。
- HashMap是基于哈希算法来确定元素的位置(槽bucket)的,当我们向集合中存入数据时,它会计算传入的Key的哈希值,并利用哈希值来确定槽的位置。
- 如果元素发生碰撞,也就是这个槽已经存在其他的元素了,则HashMap会通过链表将这些元素组织起来。
- 如果碰撞 进一步加剧,某个链表的长度达到了8,则HashMap会创建红黑树来代替这个链表,从而提高对这个槽中数据的查找的速度。
哈希表(散列表Hash table,也叫哈希表 )bucket(或称为"桶")通常指的是哈希表中的一个位置,它可以存储一个或多个键值对。哈希表是根据关键码值(Key value)而直接进行访问的 数据结构。也就是说,它通过把关键码值映射到表中的bucket来访问记录,以加快查找的速度。这个映射函数叫做 散列函数,存放记录的 数组叫做 散列表。详细可见此篇文章:
https://zhuanlan.zhihu.com/p/346539485
链表:
在理想的情况下,哈希函数将每个键均匀地散列到哈希表的各个位置。但在实际中,我们可能会遇到两个不同的键计算出相同的哈希值,这就是所谓的“哈希冲突”。HashMap通过使用链表来解决这个问题。
当哈希冲突发生时,HashMap会在冲突的bucket位置增加一个链表,新的元素会被添加到链表的末尾。每个链表中的元素都包含了相同哈希值的键值对。所以在查找元素时,如果遇到哈希冲突,HashMap需要进行一次线性查找。
哈希冲突(Hash Collision)是指在使用哈希表存储数据时,两个或多个不同的键(Key)被哈希函数映射到同一个位置的情况。这种情况会导致数据的存储和查找变得复杂,因此需要采取一些措施来解决哈希冲突。如何解决哈希冲突?详细见此博客http://t.csdnimg.cn/kt4B6
红黑树:
从Java 8开始,如果链表的长度超过一定的阈值(默认为8),那么链表会被转换为红黑树。红黑树是一种自平衡的二叉查找树,通过保持树的平衡,可以提高查找效率。
树化的规则:当链表长度超过树化阈值 8 时,先尝试扩容来减少链表长度,如果数组容量已经 >=64,才会进行树化
退化的规则:
情况 1 :在扩容时如果拆分树时,树元素个数 <= 6 则会退化链表情况 2 : remove 树节点时,若 root 、 root.left 、 root.right 、 root.left.left 有一个为 null ,也会 退化为链表
(3)hashMap扩容
何时扩容?
- JDK8扩容分两种情况,一种是元素个数超过阈值需要扩容 ,(threshold)阈值为数组长度乘以负载因子(loadFactor),loadFactor默认是
0.75f
- 一种是当链表上的元素大于8,数组个数还没到达64,无法转化为红黑树,也会进行扩容。
HashMap的扩容公式:Capacity * loadFactor = HashMap其中initailCapacity是初始容量:默认值为16(懒加载机制,只有当第一次put的时候才创建)初始容量和负载因子也可以自己设定的
HashMap 的 table 的容量如何确定?loadFactor 是什么? 该容量如何变化?这种变化会带来什么问题?
扩容原理:
容量扩展的特性:
hashMap的扩容为什么总是2的次幂?
- 容量为2的幂数则可以使元素均匀的散布hashmap中,减少hash碰撞。
- hashMap确定元素位置: (n-1)&hash
- 向集合中添加元素时,会使用(n - 1) & hash的计算方法来得出该元素在集合中的位置。只有当对应位置的数据都为1时,运算结果也为1,当HashMap的容量是2的n次幂时,(n-1)的2进制也就是1111111***111这样形式的,这样与添加元素的hash值进行位运算时,能够充分的散列,使得添加的元素均匀分布在HashMap的每个位置上,减少hash碰撞
(4)JDK1.8 中 HashMap 的 put(),get() 方法具体的一个执行流程
(5)线程安全问题
jdk1.7和jdk1.8中HashMap都是线程不安全的.
为什么是不安全的,详细请见此篇文章:http://t.csdnimg.cn/NFdFn
'解决线程安全的方式:'
- 比如使用
HashTable
- 使用
Collection.synchronizedMap
- 使用
ConcurrentHashMap
在使用HashTable或者Collection.synchronizedMap中,这两者有着共同的问题:那就是性能问题。
无论读操作还是写操作,它们都会给整个集合进行加锁,导致同一时间内其他的操作进入阻塞状态。
那么在并发环境下,能够兼顾线程安全和运行效率的情况下就要使用concurrentHashMap
ConcurrentHashMap与HashMap的区别:
- ConcurrentHashMap是线程安全的数组,它采用分段锁保证安全性。容器中有多把锁,每一把锁锁一段数据,这样在多线程访问时不同段的数据时,就不会存在锁竞争了,这样便可以有效地提高并发效率。
- 而HashMap不是线程安全,没有锁机制,在多线程环境下会导致数据覆盖之类的问题,所以在多线程中使用HashMap是会抛出异常的。
- ConcurrentHashMap对整个桶数组进行了分段;而HashMap则没有对整个桶数组进行分段。
(6)HashMap的相关面试题:
什么对象可以作为HashMap的key值?
从HashMap的语法上来讲,一切对象都可以作为Key值。如:Integer、Long、String、Object等。但是在实际工作中,最常用的使用String作为Key值。
String作为不可变对象,一旦创建就不可修改。这为HashMap的使用带来了一定的安全性。由于Key的不可变性,我们无法在HashMap中修改已存在的Key的值,这避免了在使用可变对象作为Key时可能引发的问题。
同时,String类已经实现了equals()和hashCode()方法,确保了Key的比较和哈希计算的正确性。
使用Object作为Key值的时候,自定义类中的属性改变时,导致hashCode的值也发生变化,变化后,map.get(key)因为hashCode值的变化,而无法找到之前保存的value值,同样,删除也取不到值。解决方案是重写HashCode方法
2.LinkedHashMap/TreeMap/HashTable
(1)LinkedHashMap基本概念
LinkedHashMap继承于HashMap,他继承了HashMap的方法和特性,比如内部的默认初始容量、默认负载因子、扩容机制等。但是LinkedHashMap在此基础上又进行了扩展,主要提供了元素的访问顺序上的加强。
LinkedHashMap的特性:
- 允许key为null,value为null;
- key不可以重复,value可以重复;
- 内部是以数组+双向链表实现的,JDK8以后加入了红黑树;
- 内部键值对的存储是有序的(需要注意初始化的时候accessOrder属性的设置);
- 初始容量为16,负载因子为0.75,也就是当容量达到 容量*负载因子 的时候会扩容,一次扩容增加一倍;
- 内部的键值对要重写key对象 重写hashCode()、equals();
(2)TreeMap基本概念
TreeMap是一个双列集合,是Map的子类。底层由红黑树结构构成
- map根据其键的自然顺序排序,或者根据map创建时提供的Comparator排序
- 不是线程安全的
- key 不可以存入null
- 底层是基于红黑树实现的
TreeMap的数据结构:详细见此篇文章http://t.csdnimg.cn/3CI1m
(3)HashTable基本概念
参考资料
HashMap的底层数据结构 - Native8418的文章 - 知乎
https://zhuanlan.zhihu.com/p/636054806
hashMap扩容原理http://t.csdnimg.cn/FNTFm
HashMap扩容机制 - 简书
HashMap线程安全https://blog.csdn.net/qq_44544908/article/details/129018615