HashMap

线程不安全,线程异步,键值对存值,可以用null做键,键不可以重复

原理:hashing原理

使用put(key,value)时,键调用hashcode()方法获取hashcode,找到 
bucket位置来存储entry对象。bucket中储存键对象和值对象,作为Map.Entry。

当两个对象的hashcode相同会发生什么?

因为二者的hashcode值相同,所以在bucket的位置是相同的,会发生碰 
撞,因为HashMap使用链表存储对象,这个Entry(包含有键值对的Map.Entry对象)会存储在链表中

如果两个键的hashcode相同,你如何获取值对象?

当我们调用get()方法,HashMap会使用键对象的hashcode找到bucket位 
置,因为HashMap在链表中存储的是键值对  找到bucket位置之后,会调 
用keys.equals()方法去找到链表中正确的节点,最终找到要找的值对象。 

如果HashMap的大小超过了负载因子(load factor)定义的容量,怎么办?

默认的负载因子大小为0.75,也就是说,当一个map填满了75%的 
bucket时候,和其它集合类(如ArrayList等)一样,将会创建原来 
HashMap大小的两倍的bucket数组,来重新调整map的大小,并将原来 
的对象放入新的bucket数组中。

你了解重新调整HashMap大小存在什么问题吗?

 当重新调整HashMap大小的时候,存在条件竞争,因为如果两个 
 线程都发现HashMap需要重新调整大小了,它们会同时试着调整大 
 小。在调整大小的过程中,存储在链表中的元素的次序会反过来,因为 
 移动到新的bucket位置的时候,HashMap并不会将元素放在链表的尾 
 部,而是放在头部,这是为了避免尾部遍历(tail traversing)。如果条件 
 竞争发生了,那么就死循环了。

总结

HashMap基于hashing原理,我们通过put()和get()方法储存和获取对 
象。当我们将键值对传递给put()方法时,它调用键对象的hashCode()方 
法来计算hashcode,然后找到bucket位置来储存值对象。当获取对象 
时,通过键对象的equals()方法找到正确的键值对,然后返回值对象。 
HashMap使用链表来解决碰撞问题,当发生碰撞了,对象将会储存在链 
表的下一个节点中。 HashMap在每个链表节点中储存键值对对象。
当两个不同的键对象的hashcode相同时会发生什么? 它们会储存在同 
一个bucket位置的链表中。键对象的equals()方法用来找到键值对。

链表

一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序 
是通过链表中的指针链接次序实现的。一系列节点组成,在运行时动态 
生成,每个几点有两部分:一个是存储数据元素的数据域,另一个是存 
储下一个结点地址的指针域。

你可能感兴趣的:(HashMap)