学习记录 3/24

59 阅读2分钟
  1. HashMap
    1. 默认容量是16,负载因子是0.75,拉链法解决hash冲突
    2. 如果初始化指定容量,会找到最接近的2的幂作为容量
    3. 当链表长度大于等于8时,且数组的长度大于等于64时,会将链表转化为红黑树,当链表长度小于等于6时,会将树退化为链表,如果数组小于64则会进行扩容,另外当元素个数达到容量*负载因子时也会触发扩容。当每次扩容都会扩容为原容量的2倍,即保证容量一定是2的幂。
    4. jdk1.7和jdk1.8中HashMap的实现区别:7只有链表,8会转化红黑树提高查询效率。7用头插法,8用尾插法,头插法在并发扩容时会导致死循环,并且头插法在扩容会导致链表逆序。7中扩容时rehash是重新计算hash和index,而8中进行了优化,因为数组大小一定是2的幂,所以用&运算代替取余,并且可以根据hash的最高位决定是在原来的桶中,还是在原来的桶位置+oldCap位置的桶中。
  2. LinkedHashMap
    1. 继承HashMap,但是实现了三个方法来维护双向链表
    2. 使用双向链表按照插入顺序维护元素之间的连接
    3. 支持插入顺序遍历、访问顺序遍历
    4. 可以用来实现LRU缓存
    5. 与HashMap相比,维护了双向链表,可以有序遍历元素,且迭代效率更高,但是因为维护双向链表所以插入效率相较于HashMap略有下降。HashMap的遍历时无序的。
  3. 使用JMH对HashMapLinkedHashMap进行性能测试,总的来说均摊的性能差距并不是特别大
    1. 测试环境
      • CPU:12th Gen Intel(R) Core(TM) i5-12400
      • RAM:62G
    2. 存储一千万个简单元素
      1. HashMap:2199.965 ms/op
      2. LinkedHashMap:2075.718 ms/op
    3. 遍历一千万个简单元素
      1. HashMap:652.546 ms/op
      2. LinkedHashMap:303.675 ms/op
  4. LeetCode 31.下一个排列
    1. 考察双指针和字典序定义