HashMap的实现原理

1.数据结构。

  数据存储中有数组和链表,数组通过数组的下标查询,插入时按顺序插入,所以查询快,插入慢,则链表则相反,两种存储结构的有优点也有缺点。

hashmap的储存的结构就是吸取这两种数据结构的优点组成的结构————也就是耳熟的哈希表。

      结构大概是数组里每个下标存储链表的头结点,然后每个链表数据区域和下个链表的地址。链表的数据按照key(也就是map的key)的hash值对数组的长度取摸然后存在对应的下标中。 其实hashMap的数据结构是一个线性数组,可以动态决定数组的长度,所有的数据存在hashMap的静态内部类entry里。

  头结点: 这是一个单链表最开始附加的,作用是便于找到开始节点,减少单链表的删除,插入复杂性。

  线性数组: 一个数组的长度可以动态改变。

2.数据存取实现

   transient Entry[] table; 里面3个重要属性: key,value next。key 和value是我们常用的map的key,value , next用于存在一个下标下的多个值的关系。

  数据存储在这个静态内部类里,当存的时候取 int hash=key.hashCode()值,再对数组去摸,hash%length = index.

  map。.put存的时候: entry[index] = value;

  取得时候  1. index=key.hashCode()%length 2.  value =entry[index];

map.put的时候 hash值是12 如果数组的长度16取摸是 : 12  key为A

        hash值是28 如果数组的长度16取摸是:   12  key为B  这两个值都存储在下标为12下。 用A.next()就能得到B , 下标只会存储最后一个插入的值。

当数组到达一定数量之后HashMap 通过设置的数组大小相等时执行addEntry方法里的增加数组的大小,一般是2倍,如果当index的值相同拉长了链表会影响性能,hashmap存储一个因子以一定的规则增加entry的长度。最后一点如果key是null 会优先取。putForNullKey(null) //null总是放在数组的第一个链表中

map.get的时候:1.  先判断key是否为null  有空就返回null的value值 getForNullKey(); 

         2. e.hash == hash && ((k = e.key) == key || key.equals(k)) 3个条件成立的时候才能取  key的entry key的hash值相等,entry的key相等,entry的equals返回true, 这里就验证了多个值存在一个小标中取值得问题, 虽然都存在一个同一个数组下标下,但是每个key的hashCode的值不相同,然而他们存在链表指针区域通过next属性关联在一起。

null的存储和取: putForNullKey(null)  getForNullKey();  entry[0] 都对下标0操作。

3.HashMap 初始化过程 通过

DEFAULT_INITIAL_CAPACITY = 16 创建一个数组大小为16的entry  通过
DEFAULT_LOAD_FACTOR = 0.75f; 通过一个临界值16*0.75来扩充数组.
原文地址:https://www.cnblogs.com/Seeasunnyday/p/6436368.html