# hashmap

  • 实现 1.7是数组+链表
    1.8是数组+链表+红黑树 当链表元素大于8 更换为红黑树、当缩减元素小于6更换为链表
    默认数组长度:16
    默认负载因子:0.75 在0.75负载因子下 大多数情况下是均匀分布的

处理hash冲突的方式 就是在hash数组对应的链表或者红黑树添加新的节点
计算hash使用hashCode 但是冲突的时候会使用equals去比较 判断是否添加到新节点 index=(hash(key) % 数组长度) 当计算的index相等的时候 则进行equals比较 添加进链表或者红黑树中

jdk1.7 使用hash表实现 基于冲突链表方式实现 当出现hash冲突 会在在对应的冲突链表中增加一个节点 在迭代的时候 会遍历hashtable 和冲突链表
初始容量(inital capacity) 和负载系数(load factor)影响hashMap性能
初始容量影响hashTable的大小 负载系数来指定自动扩容的临界值
当 节点数量 > 初始容量*负载因子 会触发hashMap自动扩容 这里是大于 举例 如果要插入N条数据 不触发自动扩容 需要 初始容量*负载因子+1 = N
jdk1.7HashMap结构图

jdk8及其之后主要是在冲突链表元素超过8的时候 会转换为红黑树 当元素从超过8减少少于6会转换为链表
参考 java.util.HashMap.TREEIFY_THRESHOLD java.util.HashMap.UNTREEIFY_THRESHOLD 变量 jdk8及其之后HashMap实现

  • 扩容
    jdk1.7: 建立一个新数组 把旧数组所有的元素 经过hash计算重新分配到新数组中 JDK1.7中rehash的时候,旧链表迁移新链表的时候,如果在新表的数组索引位置相同,则链表元素会倒置 jdk1.8: 建立新数组 长度为原数组的2倍(2n) 那么原来的元素要么在原index要么是原来的index+n (只需要看看原来的hash值新增的那个bit是1还是0就好了,是0的话索引没变,是1的话索引变成“原索引+oldCap”)

  • 其他关联子类

    • HashMap
      基于数组作为hash bucket
    • LinkedHashMap
      记录key顺序的hashmap
    • TreeMap: key排序的map
    • ConcurrentHashMap: 多线程安全的hashMap实现
  • 线程安全的Hashmap有哪些

    • HashTable
      历史遗留集合 在需要考虑并发情况下的hashmap 直接使用concurrentHashMap
    • ConcurrentHashMap
      jdk1.7使用锁分段 Segment
      jdk1.8使用cas+synchronized

# stream集合常用操作符

https://blog.xujiuming.com/ming/8486f105.html

基本上真正常用的 就map flatmap filter collect summary skip reduce findAny

# stream和parallelStream

parallelStream 是多线程并发处理 但是这个默认情况是使用jvm识别的核心数 性能并不高
而且限制颇多
如果遇到非要并发处理 建议还是使用线程池+自定义task 来做 可以更加精细的控制并发

# list

# linkedList 和 arrayList 区别

实现的不同 linkedList基于双向链表实现 方便插入和删除元素 顺序访问速度快 arrayList基于动态数组在插入的时候 需要移动元素

# arrayList 扩容机制

原理: 向数组添加元素会检测是否超出当前数组长度 超出了 会通过 ensureCapacity()去扩容
数组扩容讲老数组元素复制到新数组并且扩充容量为原来的1.5倍
arrayList扩容示例

# arrayList Fail-Fast机制

arrayList采用快速失败机制 通过记录modCount参数面对并发修改的时候 会快速失败

最后更新时间: 2023-08-29 05:54:48