哈希表
最简单的数据结构是数组和对象(指针)
一切复杂的数据结构都可以基于数组和对象实现
HashMap的底层实现
数组+单向链表/红黑树
HashMap类的签名上有2个泛型,分别是K,V 代表两个未知的数据类型,K是Key,V是Value
如何保证集合中元素的唯一性?
1. 遍历加比较,性能是硬伤
2. 通过哈希运算,给字符串生成指纹{(hashCode)或者说标识}
单向链表的缺点:我们不能像按索引在数组中那样随机访问任何元素。需要用额外空间存储线性表的关系,存储密度小。
当某一个链表长度超过阈值8后,此时的链表会转换成红黑树,链表树化是为了减少遍历的次数
数组和链表都是线性结构,有序不唯一;
哈希(散列)是非线性结构,无序但唯一;
HashSet 类:无序,唯一
HashSet的底层是HashMap
存储在HashSet集合中的元素,实际上存储在HashMap中key位置
存储键值对的话,用HashMap;只存储单个元素的话用HashSet;
遍历HashMap和HashSet的几种方式:
1,不可以用普通for循环,非线性结构不支持用索引号遍历,不可以用增强型for,但可以用forEach
2,可以用迭代器
(1)先获取Entry集合,然后在获取Entry集合的迭代器
(1)先获取key集合,然后在获取key集合的迭代器
遍历HashSet的几种方式
1,测试唯一性
2,测试无序性
3,遍历
1. HashMap的底层实现,HashSet的底层实现
HashMap在]DK1.8之前是数组+链表,JDK1.8之后是数组+链表/红黑树HashSet的底层是HashMap
2. HashMap的put方法的底层原理
1.根据key的hashCode计算出数组index
2.落槽时
(1).如果数组中节点为null,创建新的节点对象,把k,v存储在节点对象中,把节点对象存储在数组中
(2).如果数组的节点不为null,判断节点的key与插入元素的key是否相等
(1).相等,直接用新的k ,v覆盖原节点中的k,v
(2).不相等,判断此时节点是否为红黑树
(1).是红黑树,创建红黑树节点对象存储k,v,插入到红黑树中
(2).不是红黑树,创建链表节点对象存储k,v,插入到链表中,判断链表长度是否大于 阈值8
1.大于阈值8,链表转换为红黑树
3.判断++size是否大于阈值,是就扩容
3.HashMap的resize()扩容方法的底层原理
HashMap默认初始容量是16
resize()方法是在hashmap中的size大于阈值时或者初始化时,就调用resize方法进行扩容每次扩容的时候始终是原数组长度的2倍,即长度永远是2的n次方
扩容后节点对象的位置要么在原位置,要么偏移到两倍的位置
4. HashMap的长度为什么是2的幂次方
为了能让HashMap存取高效,尽量较少碰撞,也就是要尽量把数据分配均匀,每个链表/红黑树长度大致相同。这个实现就是把数据存到哪个链表/红黑树中的算法。
5.什么是哈希函数和哈希码
哈希函数:就是一个方法
同一个字符串使用同样的哈希函数计算出来的哈希码必是一样的
不同的字符串使用同样的哈希函数计算出来的哈希码大概率是不一样的,小概率是一样的
6.什么是哈希碰撞/哈希冲突,怎么解决哈希冲突,HashMap采用的是什么策略
1,如果有两个不同的字符串通过同样的哈希算法计算出来的哈希码是一样的,则称他们发生了哈希碰撞,哈希冲突
2,如何解决哈希冲突?
1.开放地址法
2.拉链法(链地址法)HashMap默认使用的就是这种
3,HashMap采用的是什么策略
hash() 方法用于对Key的hashCode进行重新计算,而 indexFor() 方法用于生成这个Entry对象的插入位置。当计算出来的hash值与hashMap的(length-1)做了&运算后,会得到位于区间[0,length-1]的一个值。特别地,这个值分布的越均匀, HashMap 的空间利用率也就越高,存取效率也就越好。
7. HashMap和TreeMap的区别
1,数据结构:HashMap:数组+单向链表/红黑树
TreeMap:红黑树
2. 因为数据结构,导致节点的实体类不一样
HashMap: 两种 Node 和 TreeNode (支持链表)
TreeMap :只是红黑树,不支持链表操作
3.数据范围:数据结构不一样,所以数据结构的范围,完全没有可比性
HashMap:
默认数组长度: 16
数组最大长度: 2^30
扩容因子: 0.75f
列表转红黑树阈值: 8
红黑树转列表阈值: 6
列表转红黑树最小数组长度: 64
TreeMap:没发现有范围控制
4. 线程安全:都不是线程安全的
8.如何决定使用HashMap还是TreeMap ?
对于在Map中插入、删除和定位元秦这类操作,HashMap是最好的选择。然而,假如你需要对一个有序的key集合进行逼历,Treelap是更好的选择。基于你的co1lection的大小,也许向HashMap中添加元素会更快,将map换为TreeMap进行有序key的遍历
————————————————
版权声明:本文为CSDN博主「qq_53439751」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_53439751/article/details/125612615