Java-集合-八股文

dengliang356a / 2023-07-16 / 原文

  1. list、set
  2. list:有序,可重复,允许多个null,支持下标随机访问
    set:无序,不可重复,单一null,必须遍历访问
    
  3. arraylist、linkedlist
  4. arraylist:基于数组实现,占用连续空间,有利于查找、修改,不利于插入、删除[适用场景不同]
    linkedlist:基于链表实现,不要求占用空间连续,有利于插入、删除,不利于查找、修改[适用场景不同]
    
  5. concurrenthashmap扩容机理
  6. 1.7之前:基于segment分段hashmap存储实现的,segment分段存储部分不扩容,仅内部的hashmap进行扩容[哪个线程对应的内部hashmap需要扩容,哪个线程就负责做这个事情]
    1.8之后:不是基于segment分段存储实现的,所有的K-V对都包含在一个map中,只是扩容的时候,那就每个子线程都参与扩容
    
  7. JDK版本变迁,hashmap的主要变更
  8. 1.7:底层是数组+链表,哈希算法复杂
    1.8:底层是数组+链表+红黑树,由于引入红黑树,哈希算法得到简化,从而优化hashmap的插入、查询效率
    
  9. hashmap的put方法
  10. 大体流程:
    1.依据key和哈希算法计算下标
    2.如果下标位置为空,则封装成对象(1.7:entry对象,1.8:node对象),放置该位置
    3.如果下标位置不空,
    3.1 JDK1.7:判断是否需要扩容,然后,头插法插入到对应位置的链表中
    3.2 JDK.8:判断是红黑树节点还是链表节点,然后插入到hashmap里面,最后判断扩容
    3.2.1 红黑树节点:将KV对封装成红黑树节点,加入到红黑树中
    3.2.2 链表节点:尾插法插入到对应位置的链表中,如果多于等于8个节点,将链表转为红黑树
    
  11. hashmap扩容机理
  12. 1.7:生成新数组,遍历原数组上的每个链表,将内部数据逐个转移至新数组
    1.8:生成新数组,遍历原数组上的每个链表与红黑树
    ①如果原数组上是链表,遍历每个元素,重新计算下标并转移
    ②如果原数组上是红黑树,遍历每个元素,重新计算下标并转移,有冲突再购建链表与红黑树
    
  13. copyonwriteArrayList
  14. 线程安全的arrayList,底层也是用数组实现的,主要集中在读与写操作上
    读:由于读写分别在老新数组上,因此,互相不干扰,也因此,读的性能不会受写的性能影响[适用于读多写少]
    写:写操作会生成新数组,在完成之前,其他线程无法进行写操作[上了锁,线程安全];在完成之前,读的是原数组,写的是新数组,两者是不会互相干扰的。