面试必考:HashMap的内部结构

HashMap的数据结构

    HashMap是一个非常有意思的结构, 它的整个结构是一个数组+链表的结构(当一个链表中的元素过多会重新调整成一个红黑树,这是1.7版本进行的一个改进)。

    从字面上讲,HashMap是一个map,就是一个映射性质的集合。它的一个主要功能是计算一个对象的hash值,然后通过这个hash值来直接寻找这个对象。

    通过映射的方式来查找对象,时间复杂度是O(1)。

HashMap是怎样存储数据的

    在进行创建一个HashMap的时候,如果没有向构造函数传递一个Integer的参数,那么这个HashMap的默认大小就是16,在源码中的表现是如下:    

/**
     * The default initial capacity - MUST be a power of two.
     */
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

    这个数字会在进行hash分组的时候会用到。

    当向HashMap中放入一个对象的时候,即执行put(key,value)的时候,先会对放入的key对象进行hash值的计算,在计算完成之后会得到一个int的hash值,再通过这个hash值对这个HashMap的容量(之前有说,默认容量是16)进行求余的操作,在java中是这样进行的:

(n - 1) & hash

    其中,n是HashMap的容量,这个操作等价于hash%n。在取到了这个余数之后,就得到了这个对象要放到数组的哪个槽位里。在确定了放到哪个槽位里之后,会拿放入的value值与这个槽位里所有的对象用equals方法进行比较:

    1.如果所有的对象都与value值不一样,则把这个对象放到链表的最后 

    2.如果在遍历的时候有对象与value相等,那么就把传入的对象替换它相同的对象

    这样的过程之后 ,就完成了对一个对象的放入。在这个过程中,需要注意一点:因为是先按hash分组再按equals进行存放,所以两个对象如果相等,就一定要放到数组的同一个槽位里,如果不这样做,就可能出现同一个对象出现两次,而HashMap中的所有对象都是按照hash算法得到hash值再处理的,所以没有任何的顺序可言,相同的对象是不能出现两次的。所以有了以下的结论:

    两个对象相等,就一定有相同的hash值,有相同hash值的对象不一定相等。这也是我们重写对象的hashCode()方法和equals()方法的时候需要注意的事项。

猜你喜欢

转载自my.oschina.net/u/2304814/blog/1799037