简单谈谈对HashMap集合的理解

此文适合有基础的同学阅读,不建议初学者阅读

首先基础概念:

      HashMap是线程不安全的集合,允许空键(key=null)空值(value=null),因为他是一个线程不安全的集合,允许多个线程同时操作,底层方法没有加synchronize线程锁,所以效率较高,底层为数组加单向链结构,jdk1.8的数组名称为node,jdk1.7之前的数组名称为entry,HashMap实现与jdk1.2的Map接口。HashMap允许将null作为一个entry的key或者value。

 

在HashMap的Entry中有四个变量,key、value、hash、next,其中next用于在hash方法添加值冲突时候,所指向的下一个值。

添加方法:

  1. 对key进行hash计算,用等到的hash值除以当前集合的容量,也就是数组的大小,取余数,根据余数存到对应的下标位置index。(在HashMap如果传入的key为null,hash值会设置为null,在执行添加的时候会先进行判断key的值是否为null)
  2. 如果index所指向的数组元素为空,则直接指插入,如果不为空,则依次查找entry中next所定的元素,判读key是否相等,如果相等,则替换久的值。(先是根据hash值进行判断的,如果hash值相同再进行判断key的值,因为hash值会用重复的)
  3. 如果没有相等的,将之前第一个元素entry,添加到我们待新添加的entry的next变量中。(就是将后添加的放到最前面)。

 

扩容机制:

HashMap默认的负载因子为0.75f  默认的初始大小为16

数组大小*负载因子=要调整大小的值(临界值)

 

    从源代码来看HashMap,在添加时执行扩容方法,执行扩容方法时必须两个条件同时相等,(链表的总条数>=要调整大小的值)和当前要添加的值的索引位置不为null(也就是说当前要添加值得索引位置里面有值),才会执行扩容方法,扩容的大小为原来的数组长度乘以2(原来的数组长度的二倍)。扩容之后所有元素还会根据key来重新计算hash值进行重新添加元素,重新执行顺序为下标从0开始,里面的链表从外层开始。

 

    在调用构造方法里没有开辟数组空间

 

 HashMap查询机制 :

        先根据hash值计算得到下标,然后进行遍历链表从而得到想要的值

HashMap优化:

    空间换时间:将负载因子调小,这样的话链表的长度就会变短,但是数组的长度就会变大,比较占内存,但效率就会变高。

    时间换空间:将负载因子调大,这样的话链表的长度就会变长,但是数组的长度就会变小,比较省内存,但效率就会变低。

你可能感兴趣的:(java集合)