HashMap面试

HashMap的put方法 JDK1.7

HashMap hashmap = new HashMap();

在实例化以后,底层创建一个长度是16的一维数组Entry[] table;

首先调用key所在类的hashcode()计算key的哈希值,此哈希值经过某种算法计算以后,得到entry数组中的存放位置,如果此位置上的数据为空,此时的key-value添加成功。

如果此位置数据不为空,(意味这此位置上存在一个或多个数据(以链表的形式存在)),比较key和已经存在的一个或多个数据的哈希值:

如果key的哈希值与已经存在的数据的哈希值不相同,此时key-value添加成功。

如果key的哈希值和已经存在的某个数据(key1-value1)的哈希值相相同,继续比较;调用key所在类的equals(key1),

​(2)如果equals()返回false,此时key-value添加成功。

(3)如果equals()返回true:使用value替换value1。

补充:关于情况2和情况3:此时key-value和原来的数据以链表的方式存储。

在不断添加的过程中回涉及到扩容问题,默认扩容的方式:扩容为原来容量的2倍,并将原来的数据复制过来

JDK8相较于JDK7在底层方面实现的不同

  1. new HashMap时底层没有创建一个长度为16的Node数组。
  2. 首次调用put方法,底层创建长度为16的数组
  3. JDK7底层结构只有:数组+链表 JDK8中的 底层结构
    数组+链表+红黑树​当数组的某一个索引位置上的元素以链表形式存在的数据个数>8,且当前数据的长度>64,此时此索引位置上的所有数据改为红黑树存储
<think>好的,我现在需要处理用户关于HashMap面试题目的查询。首先,用户已经提供了四个引用来源,其中引用[1]、[2]、[3]、[4]都涉及Java集合框架,特别是HashMap的相关内容。我需要根据这些引用来整理出常见的问题和答案。 首先,我需要回顾每个引用的内容。引用[1]提到了TreeSet、区分重复元素的方法、ArrayList和Vector的区别,以及Collection和Collections的区别。引用[2]讨论了HashMap与Hashtable的区别,以及可能的刁钻问题。引用[3]详细描述了JDK1.8前后HashMap的底层实现,包括扰动函数、拉链法和红黑树。引用[4]则是关于Java集合的20个问题,但具体内容未详细列出,不过可能包含更多相关问题。 用户的需求是查找HashMap面试题及答案,因此需要重点从引用[2]、[3]中提取信息,并结合其他引用中的相关内容。例如,引用[3]详细解释了HashMap的底层结构、哈希冲突解决方法和红黑树的引入,这些都是常见的面试问题。引用[2]提到了HashMap与Hashtable的区别,这也是经典问题。 接下来,我需要整理出常见的问题,并确保每个问题都有对应的解答,同时正确引用来源。例如,问题可能包括: 1. HashMap和Hashtable的区别?答案应涉及null键值、同步性等,引用[2]和[3]。 2. JDK1.8中HashMap的改进?涉及红黑树,引用[3]。 3. 哈希冲突解决方法?拉链法和红黑树,引用[3]。 4. 扰动函数的作用?引用[3]。 5. 为何HashMap不保证顺序?引用[3]或常识。 6. Collection和Collections的区别?引用[1]。 7. 其他相关问题如初始容量、载因子、线程安全等,可能需综合多个引用。 需要注意每个答案后正确标注引用来源,例如关于扰动函数的部分来自引用[3]。同时,用户要求使用中文回答,行内公式用$...$,独立公式用$$...$$,但根据问题内容可能公式较少,但需注意LaTeX语法正确。 另外,用户示例中的快速排序部分有代码块,这里可能需要针对HashMap的问题入代码示例,如扰动函数的实现,或者红黑树相关的伪代码,但需确认引用内容中是否有提供。例如,引用[3]提到扰动函数是HashMap的hash方法,可以举例代码。 最后,生成相关问题部分需要基于已整理的问题,提出扩展性问题,例如性能优化、并发处理等,可能需要结合引用中的内容或常识。 现在需要确保每个问题解答准确,引用正确,格式符合要求,并且结构清晰。可能还需要检查是否有重复问题,或者是否覆盖了用户关心的主要方面。</think>### HashMap面试问题及解答 #### 1. HashMap与Hashtable的区别是什么? - **HashMap**允许键和值为`null`,而**Hashtable**不允许[^2]。 - **HashMap**是非线程安全的(非synchronized),而**Hashtable**的方法通过`synchronized`关键字保证线程安全[^2][^3]。 - **HashMap**在JDK1.8后引入红黑树优化链表过长的问题,而**Hashtable**无此机制。 #### 2. JDK1.8中HashMap的底层实现有哪些改进? JDK1.8前,HashMap使用**数组+链表**(拉链法)处理哈希冲突;JDK1.8后,当链表长度超过阈值(默认为8)时,链表会转换为**红黑树**,以提高查询效率(时间复杂度从$O(n)$降为$O(\log n)$)。 #### 3. HashMap如何解决哈希冲突? - **拉链法**:将哈希值相同的键值对存储在链表中。 - **红黑树优化**:当链表过长时转换为红黑树(JDK1.8引入)。 #### 4. 什么是扰动函数?它的作用是什么? 扰动函数是HashMap的`hash()`方法,通过将键的哈希码的高16位与低16位异或,减少哈希冲突。例如: ```java static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); } ``` 其目的是让哈希码分布更均匀,减少低质量`hashCode()`实现的影响。 #### 5. HashMap的初始容量和载因子是什么? - **初始容量**默认为16,**载因子**默认为0.75。当元素数量超过`容量×载因子`时触发扩容(容量翻倍)。 - 公式:扩容阈值$T = \text{capacity} \times \text{loadFactor}$。 #### 6. 为何HashMap不保证元素的顺序? 因为哈希函数将键分散到不同的桶中,且扩容时可能重新哈希元素,导致顺序变化。 #### 7. Collection和Collections的区别是什么? - **Collection**是集合框架的根接口(如List、Set)。 - **Collections**是工具类,提供静态方法操作集合(如排序、同步包装)[^1]。 #### 8. HashMap为何线程不安全? 多个线程同时扩容可能导致链表成环或数据丢失。线程安全替代方案: - 使用`ConcurrentHashMap`。 - 通过`Collections.synchronizedMap()`包装。 #### 9. HashMap的`put()`方法流程? 1. 计算键的哈希值。 2. 定位到数组索引。 3. 若桶为空,直接插入;否则遍历链表/红黑树: - 键存在则更新值。 - 键不存在则插入新节点。 4. 若链表长度≥8且数组长度≥64,链表转红黑树。 #### 10. 为何JDK1.8引入红黑树而非其他数据结构? 红黑树在增删查操作上综合性能较好(平均时间复杂度$O(\log n)$),且能避免链表过长导致的性能骤降。 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值