Map 笔记

今天学习了 map 中的 hashMap 和 concurrentHashMap 区别,简单记录下。

1.JDk1.7

hashmap:

  1. hashmap 是数组和链表的组合结构,线程不安全
  2. hashmap 默认长度为 16,默认加载因子为 0.75,hashmap 添加数据时,添加后的长度大于等于原来长度*加载因子时会扩容,默认增加为原来的 2 倍
  3. hashmap 指定长度和加载因子初始化构造方法时,hashmap 的长度初始化为大于等于指定长度的 2 的次方的值
  4. hashmap 的长度总是为 2 的次方,主要是为了方便通过寻找到 entry 对象存在那个数组节点。
  5. put() 方法操作时,先通过 hashcode 位运算和与运算后得到 hash,再通过 hash & (hashmap长度-1) 寻找到entry对象存在那个数组节点,然后得到这个节点存放的链表,如果为 null,直接存放,如果不为 null,则通过 key 判断是否有自己存放的 key 的 entry,有直接替换 value,返回 oldvalue,如果没有判断链表长度,最后放在链表头部,然后存放链表原来头部 entry 的下标 next,链表下移
  6. 扩容时,数组元素中链表的顺序和原来存放的顺序刚好相反,并且会出现死循环的问题

    hashtable:线程安全,给 put() 方法加了个 synchronized,效率慢
    concurrentHashMap: 构造方法中比 hashmap 多个级别level的参数,该 map 把一个entry数组分为了 level 个,segment,并且每个都加锁,每个 segment 的长度为 map 的长度/level

2.JDK1.8

hashmap:
相对于 jdk1.7 的区别:

  1. put() 方法插入元素,追加在链表的尾部,而不是插入头部再向下移动一位
  2. 链表长度大于等于8时会树化为红黑树结构

concurrentHashMap:
相对于 jdk1.7 的区别:没有了 segment。因为每次操作都会设计链表的第一个元素,所以只给链表第一位元素加锁

如果有哪些不对的地方烦请指认,先行感谢