HashMap学习总结

来源:互联网 发布:js设计模式划分 编辑:程序博客网 时间:2024/05/21 19:30

HashMap是我们常用的一个数据结构,很多缓存都是由它实现的。下面聊聊HashMap的学习所得。

HashMap存储结构在表面上看来是key-value形式的,而它的内部结构却是一个ArrayList,是一个可以动态生长的数组,该数组的每一个元素都是一个单向链表。链表中每一个元素就如linkedLIst中每个元素类似,看下源码中链表元素Entry的构造函数:

 final K key;        V value;        Entry<K,V> next;        int hash;        /**         * Creates new entry.         */        Entry(int h, K k, V v, Entry<K,V> n) {            value = v;            next = n;            key = k;            hash = h;        }
key,value一目了然吧,next就是用来指向下一个元素,逻辑上的指针。hash就是该key的hashCode,HashMap本身对原来的hashCode又进行了一次hash计算,是不信任jdk原有的hash,这次取了高位;这个hash是用来给这个Entry对象分配一个bucket(桶),就是刚才说的数组的某个元素,当我们put一对数据的时候,hashMap就会根据这个key的hashCode给他找到一个桶,然后在遍历这个桶里的链表,遍历这个链表中的Entry,如果发现某个Entry中的key与新来的key相等——HashCode相等&&值相等(==),那么就会把这个key原有的value给替换成新的value。很麻烦吧,get取值也是这样的过程哦。

正是遍历链表的这个过程比较耗时,所以hashMap就要想办法了,不要让我的链表涨的太长;很简单嘛,让数组长点,就好了呗,可数组长了,会很耗费内存空间,因为它必须取内存红连续的地址,缩小了内存的使用率。自宇宙成型以来,空间与时间就这样相互排斥,你进我退,无言地诉说着人类理解不了的哀愁。

HashMap最终解决办法是抛出问题,让使用者自己决定,对我们使用者来说,可以通过一个参数来告诉HashMap什么时候增加数组长度,使用者可以指定一个参数,叫做阀值,默认为0.75,当HashMap的size大于阀值*数组长度的时候,hashMap数组就会自增一倍,然后重新分配key-value。这又是一个很耗时的过程,如何使用,该慎重了。

key为null的时候也可以村进来,都放在数组的第一个元素那了。

另外,HashMap是线程不安全的,HashTable用sycronized关键字对每一个方法上锁实现线程安全。

1 0
原创粉丝点击