赞
踩
目录
HashMap 的 table 的容量如何确定?loadFactor 是什么? 该容量如何变化?这种变化会带来什么问题?
(4)JDK1.8 中 HashMap 的 put(),get() 方法具体的一个执行流程
2.LinkedHashMap/TreeMap/HashTable
本文简单介绍双列集合的概念知识点,后面会出关于集合源码的详细解析
Map集合是一种以键值对形式存储和操作数据的数据结构,建立了key-value之间的映射关系,key不允许重复,value可以重复。Map常用实现类有HashMap,TreeMap,LinkedHashMap和Hashtable。
双列集合结构图:
HashMap底层基于哈希表算法,HashMap中存储的key对象的hashCode值决定了 在哈希表中的存储位置,因为HashMap中的key是Set,所以不能保证添加的先后顺序,也不允许重复。
哈希码的介绍:哈希码的主要作用是在集合中进行元素的快速查找。它通过哈希函数将键转换为一个唯一的整数,决定了键值对在数组中的存储位置。如果两个键的哈希码不同,它们会被分配到不同的桶中,提高了查找效率。如果哈希码相同,就会发生哈希冲突,需要进一步处理。
哈希表(散列表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 ,也会 退化为链表
0.75f
HashMap的扩容公式:Capacity * loadFactor = HashMap其中initailCapacity是初始容量:默认值为16(懒加载机制,只有当第一次put的时候才创建)初始容量和负载因子也可以自己设定的
jdk1.7和jdk1.8中HashMap都是线程不安全的.
为什么是不安全的,详细请见此篇文章:http://t.csdnimg.cn/NFdFn
'解决线程安全的方式:'
HashTable
Collection.synchronizedMap
ConcurrentHashMap
在使用HashTable或者Collection.synchronizedMap中,这两者有着共同的问题:那就是性能问题。
无论读操作还是写操作,它们都会给整个集合进行加锁,导致同一时间内其他的操作进入阻塞状态。
那么在并发环境下,能够兼顾线程安全和运行效率的情况下就要使用concurrentHashMap
ConcurrentHashMap与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方法
LinkedHashMap继承于HashMap,他继承了HashMap的方法和特性,比如内部的默认初始容量、默认负载因子、扩容机制等。但是LinkedHashMap在此基础上又进行了扩展,主要提供了元素的访问顺序上的加强。
LinkedHashMap的特性:
TreeMap是一个双列集合,是Map的子类。底层由红黑树结构构成
TreeMap的数据结构:详细见此篇文章http://t.csdnimg.cn/3CI1m
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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。