【Java-一些常见键值对集合面试问题】

目录

1.HashMap、LinkedHashMap、TreeMap的区别?

2..HashMap 和 Hashtable 的区别?

3.HashMap的数据结构 

4.HashMap中put()的执行过程?

5.HashMap如何计算key-value键值对元素在数组中的存储位置?

6.HashMap的扩容机制?

7.什么是哈希冲突

8.如何解决哈希冲突

9.红黑树有哪些特点

10.HashMap为什么使用红黑树

11.HashMap链表转换红黑树的条件

12.HashMap红黑树退化成链表的条件


1.HashMap、LinkedHashMap、TreeMap的区别?

 HashMap:
        数据结构:数组+链表+红黑树
        无序       
LinkedHashMap:
        数据结构:数组+链表
        有序
TreeMap: 
        数据结构:数组
        自动排序,安装key或者自定义comparator比较器排序

2..HashMap 和 Hashtable 的区别?

HashMap 和 Hashtable 都是 Map 接口的键值对集合实现类,它们的区别主要包括:
1.线程安全:
        HashMap是非线程安全的,而 HashTable 线程安全;
2.执行效率:
        由于 HashTable 使用 synchronized 同步锁实现线程安全,所以 HashTable 效率要比 HashMap 略低;
3.使用 Null 做 key 和 value:
        HashMap:可以使用 null 作为key和value;
        HashTable:不允许有 null 键和 null 值,否则会抛出 NullPointerException 异常;
3.数据结构:
        HashMap:数组+链表+红黑树;
        HashTable:数组+链表;
4.扩容方式
        HashMap:默认的初始化大小为 16。之后每次扩充,容量变为原来的 2 倍;
        HashTable:默认的初始大小为11,之后每次扩充,容量变为原来的 2n+1;

3.HashMap的数据结构 

HashMap的数据结构是数组+链表+红黑树
1.数组
        其实HashMap的数组本质上是一个哈希表,HashMap内部定义了一个数组,数组的每一个位置被称为桶(Bucket)。
        当你添加新的键值对时,会根据key的哈希值进行哈希计算算出一个新的哈希值,通过该哈希值计算该元素在数组中的下标位置。
2.链表
        当两个或更多的key-value键值对,被映射保存到数组的同一个位置(桶(Bucket)时,就产生了哈希表冲突;HashMap使用链地址法,解决给希冲突。
3.红黑树:
        为了优化链表的查询性能,当链表长度超过一个阈值(默认是)并且数姐的容量大于等于64时,链表会转换成红黑树;
        红黑树是一种自平衡的二叉查找树,它可以基于二分查找的方式,进行元素的查找,提离查找搜索性能,这对于较长的链表来说是一个明显的性能提升;

4.HashMap中put()的执行过程?

1、计算哈希码
        向HashMap 中添加一个新的key-value 键值对时,首先会调用 key 键的 hashcode() 方法来计算一个 hash 哈希值。(这个给希值将被用于计算key-value键值对,在数组中保存时的下标位置)
2、计算数组下标
        计算完hash哈希值后,HashMap会通过数组长度n,按照(n-1)&hash 的方式,将哈希值转化为数组下标:(n-1)& hash的作用等同于hash%n,位运算比算术运算的效率高;
3、处理哈希冲突
        如果不同 key按照各自不同的 hash 哈希值,计算的数组下标位置相同,这种情况称为哈希表冲突:
        Hashrtap 使用链地址法来处理哈希表冲突,在数组的每个位置存放一个链表成红黑树(当链表长度达到一定阈值时会转换为
4、检查健是否已存在
        在将键值对放入对应位置之前,HashMap会查该位置是否存在与新相等的对象;
会调用 equals()方法来比较键之间的相等性,如果找到相同的键,那么旧的值将被新值替换,返回旧值;否则,新键值对将被添加;
5、插入新节点:
        如果没有找到相等的键,新键值对将被插入到该位置的链表头部或红黑树中;
        当链表长度达到8且数组容量大于64时,链表会转化为红黑树,用来优化查找性能;
6、检查容量和扩容:
        每次插入新键值对后,HashMap 会检查当元素数量否超过了它的扩容阅值(容量乘以加载因子(默认为0.75));
        如果超过了扩容阈值,HashMap 会按照2倍进行扩客
7、返回旧值:
        如果在插入过程中发现键已经存在,put)方法会返回旧的值;
        如果键不存在,插入了一个新键值对,put()方法将返回 nu11  

5.HashMap如何计算key-value键值对元素在数组中的存储位置?

        为了使 key-value 元素可以均匀散列的保存在 HashMap 的数组中,所以使用key 的哈希值进行哈希扰动计算出一个新的 has h值。
        在JDK 1.8 版本以前, HashMap 会将这个 hash 值与数组长度进行%模运算出一个下标值,从而确定 key-value 在数组中的存储位置。
        在JDK1.8版本以后,由于%运算性能消耗比较大,所以采用(长度﹣1)& hash 的位运算方式来计算存储位置。 

6.HashMap的扩容机制?

HashMap 的用来进行扩容的方法是 resize()方法;
HashMap 在以下三种场景下,会触发扩容机制:
        1.当 HashMap 通过无参构造方法创建,在第一次调用 put()方法添加 key-value键值对时,数组初始化为16;
        2.当 HashMap 中的元素个数超过扩容阈值 threshold 时,数组的容量按照原容量的2倍进行扩容:
                .扩容阈值 threshold = 数组容量 x 加载因子 LoadFactor;
                .加载因子 LoadFactor 的默认值为0.75,数组容量默认为 16,扩容阈值 threshold 默认为 12;
                .所以,当 HashMap 中元素个数超过 12 时,数组的容量按照原容量的 2 倍进行扩容;
        3.加入元素时,如果链表长度大于阈值(默认为8)并且数组长度小于64,会产生数组扩容; 

7.什么是哈希冲突

        哈希冲突是在使用哈希函数或哈希表时遇到的一种特殊情况;
        如果发生在哈希函数,哈希冲突是指当发生在两个不同的输入值,经过哈希函数处理后产生了相同的哈希值;
        如果发生在哈希表,哈希冲突是因为哈希表的大小有限,可能输入不同数据在表中计算的下标位置冲突。 

8.如何解决哈希冲突

处理哈希冲突的方法主要有以下几种:
1.开放寻址法(Open Addressing):
        当哈希冲突发生时,使用某种探测技术在哈希表中寻找下一个空位来存储数据。
2.链地址法(Chaining):
        每个哈希表的槽位都维护一个链表。当哈希冲突发生时,所有哈希值相同的元素都被存储在同一个位置对应的链表中。
3.再哈希法(Rehashing):
        当哈希冲突发生时,使用第二个哈希函数再次计算哈希值,直到找到空槽位。这种方法会增加计算复杂度,但可以减少哈希表的装载因子,从而提高查找效率。
4.建立一个公共溢出区:
        将哈希表分为基本表和溢出表两部分。所有哈希地址不冲突的元素放在基本表里,所有哈希地址冲突的元素存放在溢出表中。 

9.红黑树有哪些特点

红黑树是一种自平衡二叉查找树:
        二叉查找树:树中的所有节点满足排序规则(left < root < right),可以基于二分查找进行搜索;
        自平衡:保持左右子树的平衡,保持搜索性能。不会出现退化成链表的极端情况(所有子节点都保存在左子树或右子树);
        所以,HashMap 使用红黑树来优化长链表; 

10.HashMap为什么使用红黑树

        HashMap 中的链表长度增长到一定长度,会导致搜索性能下降;(链表是线性方式搜索)
所以,HashMap 会在链表过长时,将链表转换为红黑树,通过红黑树提供搜索性能;
        HashMap 不直接用红黑树的原因是:链表简单易于维护,红黑树维护复杂。所以首选使用链表,只有链表长度过长时,才会转换成红黑树来提高搜索查找的性能; 

11.HashMap链表转换红黑树的条件

        在HashMap 中,当链表转换为红黑树,需要同时满足两个条件:链表长度大于等于8,并且数组容量大于等于64;
        1.链表长度:当链表的长度大于等于 8时(有8个或更多的元素在 HashMap的同一个桶。这是因为在链表长度较小的情况下,链表的线性查找效率还可以接受,但是一旦当链表长度较长时,必须通过将链表转换成红黑树这种方式,才能够提供更好的查找性能。
        2.数组容量:在链表达到阈值8时,同时还要检查 HashMap 的底层数组(哈希表)的容量大于等于64,因为 HashMap 不会轻易使用红黑树,虽然红黑树的搜索性能比链表好,但是维护更复杂。只有在链表足够长,只有红黑树才能带来明显性能提升时,才会进行转换。
        所以,如果数组容量小于64,即使链表长度超过 8,也不会立即进行红黑树的转换,而是先进行数组的扩容,将HashMa p中的所有元素重新散列保存,用来降低链表的长度。 

12.HashMap红黑树退化成链表的条件

        当红黑树中的节点数量减少到 6 个或更少时,红黑树将转换回链表;
因为,红黑树中的节点过少时,使用链表来保存,维护会更简单高效; 

  • 13
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值