JDK中的HashMap;
HashMap<k,v> map = new HashMap<?,?>();
HashMap的结构组成:由数组+链表实现;每个数组中都存储着一个单向链表。
那如何来进行存储呢?
大家都知道,ArrayList的结构为数组组成,其中主要方法为add(),将一个元素加入到ArrayList中,而在数组的存储特点是:顺序存储,每个值都带有一个“下标”,通过下标值就能娶到对于的元素;
由ArrayList源码分析所知:add()方法是通过计算当前的数组下标size,通过++size,然后在将元素存储在下标为size+1的位置。这样就完成了该元素存入数组中。
而HashMap是如何put呢,如何去确定存储的位置呢
1.确定存储位置
HashMap由数组+链表组成,那么数组初始化的时候是有一个初始化大小size的,那么HashMap的存储位置是通过计算K值的Hashcode值,然后用哈希值对数组的大小size进行取余操作,这样就能够确定value存储的位置。并且取余操作能够保证每个K的哈希值都是比较平均的分布在数组各个下标位置。
2.确定值的具体位置
HashMap由数组+链表组成,hash值取余操作确定了具体的存储数组下标位置。而具体的value值则是放在数组中具体的每个单向链表中。
当初次将值加入到链表中时,链表为空的,所有第一个值肯定是位于该链表的头结点(header-node);
当第二次将值插入到链表中,应该怎么进行插入操作,使得这个插入操作更快的完成呢?
由于链表的结构特点,导致链表具有“增删快,插入慢”的特点,使得每次向链表中插入值,都需要遍历整个链表,当循环到最后一个节点(node.next==null)时,再将需要插入的节点插入到最后一个节点的next位置。
显然,这种“尾插法”,每次插入都要遍历整个链表,所有HashMap的value存储到链表中都是采用“头插法”来操作的,每次豆新的node值存储在头结点,使得操作最快捷。
单向链表中的每个元素都由“具体值和下一个值的引用“(value+next)来组成,数组中下标中存放的值都是链表中的头结点的引用,那每当有一个新的node值插入到链表中的时候,链表的头结点就换成了最新插入的那个节点值,所以每次将新节点插入到链表中之后,还需要将对于数组下标的引用值换成最新的节点引用值。
由此以上就完成了一个<k,value>存储put到hashMap中。