Erlo

Java数据结构之004#sql_zs#HashMap

2020-09-20 21:00:21 发布   290 浏览  
页面报错/反馈
收藏 点赞

数组和链表都是存储一个对象,HashMap 存储数据是以 一对数据来存储,即键值对【key(对象)---->value(对象)】。

JDK1.8版本之前,HashMap的实现: 数组 + 链表;

JDK1.8版本之后,HashMap的实现: 数组 + 链表 / 二叉树(红黒树);

数组的默认大小是16,加载因子【DEFAULT_LOAD_FACTOR】默认值是0.75f,表示当数组容量达到75%,数组会被重新扩充。数组的最大容量是整数最大值的一半。

 

HashMap存储数据结构中链表与二叉树的转化条件:  是键值对的总数大于64,且

a.在扩容时,当哈希表中数组同一个位置的链表长度大于8时(阀值),那么会把链表转换成红黑树,来提高查询效率;

b.在扩容时,当哈希表中数组同一个位置的链表长度小于6时(阀值),那么会把红黑树转换成链表,来提高查询效率。

阀值为什么是8 和 6? (防抖)减少链表与二叉树之间的转换频率,避免影响性能。

 

哈希表:这个是因为存储数据的方式被称为哈希(算法),Object类中hashCode方法是一个本地方法:表示此方法的具体实现是由 C、C++来实现的,哈希值()。

    同一个对象,我们要保证在运行期hashCode值是相同的,如果不同那么此对象在哈希表中会有内存泄露问题。

内存泄露:由于对象在运行过程中,hashCode不同,导致该对象在哈希表中无法找到。

哈希表存储数据的算法:通过计算key对象的hashCode值,来确认key对象在哈希表数组中的存储位置,目的是为了可以通过计算hash值快速的查找对象。同一个对象,hashCode值相同,不同的对象,hashCode可能相同,因为整数是有限的。

使用hashCode计算对象的hash值:return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16)。

 

怎么扩容?初始化大小?

a.在第一次put数据的时候初始化;

b.在put方法中实现,扩容算法是 oldCap << 1  表示乘于2;

c.每次扩容哈希表,会导致所有已存储的对象重新计算哈希值,存储到新的哈希表中(重新散列)。所以在hashMap中,对象所在的位置不保证永远不变(无序),重新散列会导致重新计算所有对象,消耗性能,在可预知的情况下,散列次数越少越好。

 

HashMap的优点与缺点?

优点:取值快,数据量越大越明显;

缺点:线程不安全,避免频繁散列(rehash)。合理的使用new HashMap<>(initialCapacity);初始容量,来减少散列。

 

登录查看全部

参与评论

评论留言

还没有评论留言,赶紧来抢楼吧~~

手机查看

返回顶部

给这篇文章打个标签吧~

棒极了 糟糕透顶 好文章 PHP JAVA JS 小程序 Python SEO MySql 确认