【Java集合】经典面试题总结-史上最全面试题思维导图总结(2022最新版)

写在前面

🍁个人主页:HNUJSY
✨本期专栏:《史上最全经典面试题总结》欢迎订阅学习~
📌Xmind文件获取:GitHub 持续更新中,别忘了 star 喔~


「Java学习+面试指南」思维导图,计算机自学指南,包括Java基础、JVM、数据库、mysql、redis、计算机网络、算法、数据结构、操作系统等,后台技术栈/架构师之路/全栈开发社区,阿里,腾讯,百度,美团,头条等春招/秋招/校招/面试

序号内容链接
1Java集合经典面试题总结https://blog.csdn.net/HNUPCJ/article/details/127456294
2JVM经典面试题总结https://blog.csdn.net/HNUPCJ/article/details/127456365
3MySQL经典面试题总结https://blog.csdn.net/HNUPCJ/article/details/127453408
4Redis经典面试题总结https://blog.csdn.net/HNUPCJ/article/details/127456253
5并发编程经典面试题总结https://blog.csdn.net/HNUPCJ/article/details/127457663
6分布式系统经典面试题总结https://blog.csdn.net/HNUPCJ/article/details/127457871
7高可用架构经典面试题总结https://blog.csdn.net/HNUPCJ/article/details/127458014
8Java项目经典面试题总结https://blog.csdn.net/HNUPCJ/article/details/127458047
9安全经典面试题总结https://blog.csdn.net/HNUPCJ/article/details/127457801
10数仓经典面试题总结https://blog.csdn.net/HNUPCJ/article/details/127458107

思维导图(png格式可下载放大)

在这里插入图片描述

java集合

List

Arraylist

  • 数组
    • 查找、尾增删快
      • 增加 50%

LinkedList

  • 双向循环链表
    • 删除、插入快

Vector

  • 线程安全
    • Synchronized
      • 扩容每次会增加 1 倍

Collections.synchronizedList

CopyOnWriteArrayList

  • 写入将导致创建整个底层数组的副本,而源数组将保留在原地,使得复制的数组在被修改时,读取操作可以安全地执行
    • 合适读多写少的场景
    • 需要拷贝数组,会消耗内存
    • 不能用于实时读的场景,像拷贝数组、新增元素都需要时间
    • 没法保证 CopyOnWriteArrayList 到底要放置多少数据,万一数据稍微有点多,每次 add/set 都要重新复制数组
  • 加锁 + 数组拷贝+ volatile
    • 1.加锁:保证同一时刻数组只能被一个线程操作;
    • 2.数组拷贝:保证数组的内存地址被修改,修改后触发 volatile 的可见性,其它线程可以立马知道数组已经被修改;
    • 3.volatile:值被修改后,其它线程能够立马感知最新值
    • 1.volatile 关键字修饰的是数组,如果我们简单的在原来数组上修改其中某几个元素的值,是无法触发可见性的,我们必须通过修改数组的内存地址才行,也就说要对数组进行重新赋值才行。
    • 2.在新的数组上进行拷贝,对老数组没有任何影响,只有新数组完全拷贝完成之后,外部才能访问到,降低了在赋值过程中,老数组数据变动的影响。

Set

TreeSet

  • TreeMap

LinkedHashSet

  • LinkedHashMap

HashSet

  • HashMap
    • HashSet的值存放于HashMap的key上,HashMap的value统一为PRESENT

set只能用迭代,因为他无序,无法用下标来取得想要的值

Map

TreeMap

  • 有序
    • 红黑树
      • 对一个有序的key集合进行遍历
  • 在排序时如何比较元素
    • 实现 Comparable 接口compareTo()方法
  • Collections 工具类中的 sort()方法
    • 第二个参数,参数是Comparator 接口的子类型(需要重写 compare 方法实现元素的比较),通过接口注入比较元素大小的算法

LinkedHashMap

  • 双向链表
    • 保持插入顺序

HashMap

  • jdk7
    • 数组+链表
      • 扰动处理 = 9次扰动 = 4次位运算 + 5次异或运算
        • 头插法(先讲原位置的数据移到后1位,再插入数据到该位置),高并发可能会出现循环链表问题
          • 扩容 hashCode ->> 扰动函数 ->> (h&length-1)
            重新去计算其Hash值,根据Hash值对其进行分发
  • jdk8
    • 大于阈值(默认为8),数组+红黑树,从原来的O(n)到O(logn)
      • 扰动处理 = 2次扰动 = 1次位运算 + 1次异或运算
        高16bit不变,低16bit和高16bit做了一个异或
        两次就够了,已经达到了高位低位同时参与运算的目的
        • 尾插法(直接插入到链表尾部/红黑树)
          • 扩容 扩容后的位置=原位置 or 原位置 + 旧容量
  • hashCode()与equals()
    • 每个对象生成的hashcode通过hash分桶,再通过equals判断是否相同
    • equals方法被覆盖过,则hashCode方法也必须被覆盖
  • put
    • hash 高16bit不变,低16bit和高16bit做了一个异或,目的是减少碰撞
      • 计算下标index = (table.length - 1) & hash
        • null直接添加,不为空使用equals判断是否相同进行覆盖或者添加
          • size是否超多了最大容量threshold,扩容或者红黑树
  • 扩容
    • 初始大小为16,扩展2倍,Threshold 0.75
      • 要么在原位置,要么移动到原偏移量两倍的位置
        • HashMap 的长度为什么是2的幂次方
          取余(%)操作中如果除数是2的幂次则等价于与其除数减一的与(&)操作
          提高运算效率
          &操作 1111取模

HashTable

  • synchronized 全表锁
    • 初始大小为11,之后每次扩充,容量变为原来的2n+1

ConcurrentHashMap

  • jdk7
    • 分割分段(Segment),Segment + HashEntry,分段锁
      • 默认分配16个Segment,比Hashtable效率提高16倍
  • jdk8
    • Node 数组+链表+红黑树
      • synchronized 和 CAS 粒度为一个节点
        • 只锁定当前链表或红黑二叉树的首节点
          • Node还没有初始化,CAS插入
          • Node不为空,且当前该节点不处于移动状态,则对该节点加synchronized锁

知识

fail-fast

  • modCount
    • 内容发生变化,就会改变modCount的值
    • Iterator遍历的时候,检测modCount变量是否为expectedmodCount值,是的话就返回遍历;否则抛出ConcurrentModificationException 异常,终止遍历。

集合不能被修改

  • 使用 Collections. unmodifiableCollection(Collection c) 方法来创建一个只读集合

移除 Collection

  • 使用 Iterator.remove() 方法

    Iterator it = list.iterator();
    while(it.hasNext()){
    // do something
    it.remove();
    }
    for(Integer i : list){
    list.remove(i)
    }
    会报 ConcurrentModificationException 异常。这是因为当使用 foreach(for(Integer i : list)) 语句时,会自动生成一个iterator 来遍历该 list,但同时该 list 正在被 Iterator.remove() 修改。Java 一般不允许一个线程在遍历 Collection 时另一个线程修改它。

Iterator 和 ListIterator

  • Iterator
    • 遍历 Set 和 List 集合,只能单向遍历
  • ListIterator
    • 遍历 List,可以双向遍历
      • 添加了一些额外的功能,添加一个元素、替换一个元素、获取前面或后面元素的索引位置

遍历方式

  • for 循环遍历,基于计数器
  • 迭代器遍历,Iterator
  • foreach 循环遍历,foreach 循环遍历
    • 只能做简单的遍历,不能在遍历过程中操作数据集合,例如删除、替换。

ArrayList 的 elementData 加上 transient

private transient Object[] elementData;

  • 不希望 elementData 数组被序列化,重写了 writeObject 实现

    private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException{
    // Write out element count, and any hidden stuff
    int expectedModCount = modCount;
    s.defaultWriteObject();
    // Write out array length
    s.writeInt(elementData.length);
    // Write out all elements in the proper order.
    for (int i=0; i<size; i++)
    s.writeObject(elementData[i]);
    if (modCount != expectedModCount) {
    throw new ConcurrentModificationException();
    }

    • 先调用 defaultWriteObject() 方法序列化 ArrayList 中的非 transient 元素,然后遍历 elementData,只序列化已存入的元素

==与equals的区别

  • ==
    • 指向同一个内存空间,引用是否相同
  • equals
    • 所指向的内存空间的值是不是相同

BlockingQueue

  • 用于实现生产者-消费者模式
    • 在进行检索或移除一个元素的时候,它会等待队列变为非空;当在添加一个元素时,它会等待队列中的可用空间
      • 如果没有元素 poll()会返回 null,而 remove()会直接抛出 NoSuchElementException 异常。
      • add和offer

Array 和 ArrayList

  • array 数组
    • Arrays. asList(array)
  • ArrayList 集合
    • toArray()

Collection 和 Collections

  • collection 集合类的一个顶级接口
  • Collections 工具类/帮助类
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值