Java数据结构之004--HashMap

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

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

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

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

 

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

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

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

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

 

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

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

内存泄露:因为对象在运行过程当中,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);初始容量,来减小散列。

相关文章
相关标签/搜索