HashMap知识总结

总结:

以下都是个人的学习总结整理,如有错误,欢迎评论指出

一、HashMap类

实现了Map、Cloneable、Serializable接口,继承AbstractMap类

public class HashMap<K,V> extends AbstractMap<K,V>
    	implements Map<K,V>, Cloneable, Serializable
    	
 	/**
     * Map接口: 实现键值对,Map接口规定了一个key对应一个value
     *          HashMap使用该接口用来替换Dictionary类
     *
     * AbstractMap类: 继承Map的抽象类,减少Map操作的实现
     *
     * Cloneable接口: 可以显示的调用Object.clone()方法,合法的对该类
     *                实例进行字段复制
     *
     * Serializable接口: 实现该接口后,该类可以被序列化和反序列化
     */

二、HashMap是否线程安全?

HashMap不是线程安全的,在并发的场景下使用ConcurrentHashMap代替

三、HashMap的内部实现是什么?

内部实现:数组 + 链表 + 红黑树 (JDK 1.8之后才加上了红黑树)

数组特点:查找快,时间复杂度为O(1);删除慢,时间复杂度为O(n)
链表特点:查找慢,时间复杂度为O(n); 插入/删除快,时间复杂度为O(1)

ArrayList 使用的就是数组
LinkedList 使用的是链表,而且LinkedList是一个双向链表

四、HashMap其余知识点

1. HashMap扩容后,索引位置变化
HashMap触发扩容后,阈值会变成原来的两倍,并且会对所有节点进行重Hash分布,重Hash分布后节点的新位置只可能在两个"原索引的位置“ 或者 “原索引+原容量的位置”
(例:HashMap默认容量为16,默认负载因子为0.75,所以默认阈值为12;扩容后阈值会变成24,容量为32)
(例:原容量capacity为16,扩容前,索引位置是5的节点,扩容后,只可能分布在新表的"索引位置5"或者"索引位置21(5+16)")

2. 导致HashMap扩容后,同一索引位置的节点重Hash最多分布在两个位置的原因
(1) 哈希表的长度始终是2的幂次方
(2) 索引位置的计算方法是 (table.length - 1) & h ( 哈希值 与 表长度-1 的 位与运算)

3. 如何优化HashMap?
由于HashMap扩容是一个比较耗时的操作,定义HashMap时指定初始容量,即指定HashMap的大小

4. JDK8为什么要把链表改成红黑树?
链表查找的时间复杂度为O(n),如果链表越长,查询越慢;而红黑树各种操作的时间复杂度为O(logn)
(红黑树查询效率远大于链表,但是插入/删除操作却比链表要慢)

5. JDK 1.8 中 链表 转 红黑树
当同一个索引位置的节点在增加后达到9个时,若此时数组的长度大于等于64时,则会将链表节点(Node)转红黑树节点(TreeNode),转为红黑树节点后,链表结构其实还是存在的,通过next属性维持。如若节点个数达到9个,但是数组长度不足64时,则不会触发链表转红黑树,而是只进行数组扩容

6. JDK 1.8 中 红黑树 转 链表
当同一索引位置的节点在移除后只有6个时,而且该节点为红黑树节点时,则会触发红黑树转链表

7. JDK 1.8 之前HashMap存在死循环问题
造成原因:由于数组扩容后,同一索引位置的节点顺序会反掉

8. HashMap 与 HashTable 的区别

HashMapHashTable
允许 key 或者 value 为 null不允许 key 或者 value 为 null
初始容量为 16初始容量为 11
扩容为原来的 2 倍扩容为原来的 2 倍加 1
线程不安全线程安全
hash值是重新计算的直接使用hashCode
采用异步处理方式,性能更高采用同步处理方式,性能相对较低

9. 重写equals()方法后,是否一定要重写hashCode()方法?为什么?
重写equals()方法后,需要重写hashCode()方法。
hashCode规定:
两个对象相等(即equals()返回true),hashCode一定相同;两个对象hashCode相同,两个对象不一定相等;
重写equals,而不重写hashCode方法,默认调动Object类的hashCode()方法,会导致两个对象equals结果相同,但是hashCode()不同。简言之,重写equals方法后,重写hashCode方法就是为了确保比较的两个对象是同一对象

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值