使用一个
Entry 数组来存储数据,用
key的 hashcode 取模来决定key会被放到数组里的位置,如果 hashcode 相
同,或者
hashcode 取模后的结果相同(
hash collision ),那么这些
key 会被定位到
Entry 数组的同一个
格子里,这些
key 会形成一个链表。
在
hashcode 特别差的情况下,比方说所有
key的 hashcode 都相同,这个链表可能会很长,那么 put/get 操作
都可能需要遍历这个链表,也就是说时间复杂度在最差情况下会退化到
O(n)
JDK1.8
中
使用一个
Node 数组来存储数据,但这个
Node 可能是链表结构,也可能是红黑树结构
如果插入的
key 的
hashcode 相同,那么这些
key也会被定位到 Node 数组的同一个格子里。
如果同一个格子里的
key不超过8个,使用链表结构存储。
如果超过了
8个,那么会调用
treeifyBin 函数,将链表转换为红黑树。
那么即使
hashcode 完全相同,由于红黑树的特点,查找某个特定元素,也只需要
O(log n)的开销
也就是说
put/get的操作的时间复杂度最差只有
O(log n)
听起来挺不错,但是真正想要利用
JDK1.8 的好处,有一个限制:
ke
y
的对象,必须正确的实现了 Compare 接口
如果没有实现
Compare 接口,或者实现得不正确(比方说所有
Compare 方法都返回
0)
那
JDK1.8 的
HashMap 其实还是慢于
JDK1.7 的
简单的测试数据如下:
向
HashMap 中 java后端基础题目
put/get 1w 条
hashcode 相同的对象
JDK1.7:
put 0.26s
, get 0.55s
JDK1.8
(未实现 Compare
接口): put 0.92s
, get 2.1s
但是如果正确的实现了
Compare 接口,那么
JDK1.8 中的
HashMap 的性能有巨大提升,这次
put/get
100W条
hashcode
相同的对象
JDK1.8
(正确实现 Compare
接口,): put/get
大概开销都在320 ms
左右
f
i
n
a
l
f
i
n
a
l
l
y
f
i
n
a
l
i
z
e
final
可以修饰类、变量、方法,修饰类表示该类不能被继承、修饰方法表示该方法不能被重写、修饰变量表
示该变量是一个常量不能被重新赋值。
finally
一般作用在try-catch
代码块中,在处理异常的时候,通常我们将一定要执行的代码方法finally
代码块
中,表示不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代码。
finalize
是一个方法,属于Object
类的一个方法,而Object
类是所有类的父类,该方法一般由垃圾回收器来调
用,当我们调用
System.gc() 方法的时候,由垃圾回收器调用
finalize(),回收垃圾,一个对象是否可回收的
最后判断。
对象的四种引用
强引用
只要引用存在,垃圾回收器永远不会回收
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.bianchenghao6.com/h6javajc/1719.html