当前位置: 首页 > news >正文

java面试中经常会问到的集合问题有哪些(基础版)

文章目录

      • 一、集合框架整体架构
      • 二、List 接口
      • 三、Set 接口
      • 四、Map 接口
      • 五、集合共性问题
      • 总结

Java 集合框架是面试中的基础且高频考点,问题主要围绕 核心接口、实现类特性、底层数据结构、线程安全、性能对比 等展开。以下是常见问题及解析:

一、集合框架整体架构

  1. Java 集合框架的整体结构是什么?主要接口有哪些?
  • 集合框架分为 Collection(存储单元素)和 Map(存储键值对)两大体系:
    • Collection
      • List(有序、可重复):ArrayListLinkedListVector
      • Set(无序、不可重复):HashSetLinkedHashSetTreeSet
      • Queue(队列,FIFO):LinkedList(实现了 Queue)、PriorityQueue
    • Map(键值对映射):HashMapLinkedHashMapTreeMapHashtableConcurrentHashMap
  • 核心接口关系:CollectionMap 是顶层接口,无继承关系;ListSet 继承 CollectionQueue 继承 Collection 并扩展队列操作。
  1. Collection 和 Collections 的区别?
  • Collection:接口,定义了集合的基本操作(如 add()remove()iterator()),是 ListSet 等的父接口。
  • Collections:工具类,提供静态方法操作集合(如排序 sort()、线程安全包装 synchronizedList()、求最大值 max())。

二、List 接口

  1. ArrayList 和 LinkedList 的区别?

    维度ArrayListLinkedList
    底层结构动态数组(连续内存)双向链表(非连续内存)
    随机访问快(get(index) 时间 O(1))慢(需遍历链表,O(n))
    增删操作中间增删慢(需移动元素,O(n))中间增删快(只需修改指针,O(1))
    内存占用少(仅存元素)多(需存储前后指针)
    适用场景读多写少、随机访问频繁写多(中间增删)、队列/栈操作
  2. ArrayList 的扩容机制?

  • 初始容量:默认 10(JDK 1.8 后延迟初始化,首次 add 时才分配容量)。
  • 扩容触发:当元素数量(size)超过当前容量时,触发扩容。
  • 扩容规则:
    • 新容量 = 旧容量 × 1.5(如 10 → 15 → 22…)。
    • 若扩容后仍不足(如添加大量元素),直接扩容到所需容量。
  • 扩容过程:创建新数组,复制旧数组元素(Arrays.copyOf()),耗时且消耗内存,建议初始化时指定容量(如 new ArrayList(1000))。
  1. Vector 和 ArrayList 的区别?
  • 线程安全Vector 所有方法加 synchronized(线程安全),ArrayList 非线程安全(性能更高)。
  • 扩容机制Vector 默认扩容为原容量的 2 倍(可指定增长因子),ArrayList 为 1.5 倍。
  • 替代方案:多线程场景用 CopyOnWriteArrayList(比 Vector 高效),单线程用 ArrayList
  1. CopyOnWriteArrayList 的原理?适合什么场景?
  • 原理:写时复制,修改元素时复制一份新数组,修改完成后替换旧数组,读操作无锁(直接读旧数组)。
  • 优点:读操作高效(无锁),线程安全。
  • 缺点:内存占用高(双数组),写操作耗时(复制数组),不保证实时性(读可能看到旧数据)。
  • 适用场景:读多写少(如配置缓存、黑名单)。

三、Set 接口

  1. HashSet、LinkedHashSet、TreeSet 的区别?

    特性HashSetLinkedHashSetTreeSet
    底层结构哈希表(HashMap 实现)哈希表 + 双向链表红黑树(自平衡二叉查找树)
    有序性无序插入顺序(链表维护)自然排序或定制排序(Comparator
    去重依据hashCode() + equals()同 HashSetcompareTo()compare()
    性能读写 O(1)读写 O(1)(略低于 HashSet)读写 O(logn)
  2. HashSet 如何保证元素不重复?

  • HashSet 底层依赖 HashMap 实现(元素存在 HashMap 的 key 中,value 为固定对象)。
  • 去重逻辑:添加元素时,先计算 hashCode() 找到哈希桶,再通过 equals() 比较桶内元素,若两者都相同则视为重复,拒绝添加。
  • 关键:自定义对象需重写 hashCode()equals(),且保证“相等的对象必须有相等的哈希码”。
  1. TreeSet 如何实现排序?
  • 两种排序方式:
    • 自然排序:元素实现 Comparable 接口,重写 compareTo() 方法(如 IntegerString 默认排序)。
    • 定制排序:创建 TreeSet 时传入 Comparator 接口实现类(如 new TreeSet<>(Comparator.reverseOrder()))。
  • 底层红黑树通过比较结果(compareTo()compare() 的返回值)维护有序性,返回 0 时视为重复元素。

四、Map 接口

  1. HashMap 和 Hashtable 的区别?

    特性HashMapHashtable
    线程安全非线程安全线程安全(方法加 synchronized
    存储 null允许 key 和 value 为 null(key 仅一个 null)不允许 key 或 value 为 null
    底层结构JDK 1.8 前:数组 + 链表;1.8 后:数组 + 链表/红黑树数组 + 链表
    扩容机制初始容量 16,扩容为 2 倍,负载因子 0.75初始容量 11,扩容为 2 倍 + 1,负载因子 0.75
    迭代器快速失败(fail-fast安全失败(fail-safe
  2. HashMap 的底层数据结构?JDK 1.8 有哪些优化?

  • JDK 1.7:数组(哈希桶) + 链表(解决哈希冲突)。
  • JDK 1.8:数组 + 链表/红黑树(当链表长度 ≥ 8 且数组容量 ≥ 64 时,链表转为红黑树;当长度 ≤ 6 时,红黑树退化为链表)。
  • 优化点:
    • 红黑树提升查询性能(链表 O(n) → 红黑树 O(logn))。
    • 取消 Entry 类,改用 Node 类。
    • 扩容时计算新索引的方式简化(e.hash & (newCap - 1) 替代重新计算哈希)。
  1. HashMap 的扩容机制?
  • 触发条件:当元素数量(size)> 容量 × 负载因子(默认 16 × 0.75 = 12)时,触发扩容。
  • 扩容过程:
    1. 新容量 = 旧容量 × 2(保证容量为 2 的幂,便于哈希计算)。
    2. 创建新数组,将旧数组元素重新哈希到新数组(JDK 1.8 优化:通过高位哈希值判断索引是否需要 + 旧容量,避免重新计算哈希)。
    3. 红黑树在扩容时可能拆分为两个链表或红黑树。
  1. LinkedHashMap 如何保证插入顺序或访问顺序?
  • 底层:哈希表 + 双向链表(继承 HashMap,在 Node 中增加 beforeafter 指针)。
  • 顺序控制:
    • 插入顺序:默认模式,链表按元素插入顺序排列。
    • 访问顺序:构造时指定 accessOrder = true,每次 get()put() 操作后,将元素移到链表尾部(最近访问的元素在末尾)。
  • 应用:实现 LRU 缓存(通过重写 removeEldestEntry() 方法,移除最久未访问元素)。
  1. TreeMap 的底层结构和排序方式?
  • 底层:红黑树(根据 key 排序,保证 keySet() 遍历有序)。
  • 排序方式:同 TreeSet,支持自然排序(Comparable)和定制排序(Comparator)。
  • 适用场景:需要按 key 排序的映射(如排行榜、区间查询)。
  1. ConcurrentHashMap 和 Hashtable 的区别?JDK 1.7 和 1.8 的 ConcurrentHashMap 实现有何不同?
  • 与 Hashtable 的区别:

    • 线程安全实现:ConcurrentHashMap 用分段锁(1.7)或 CAS + synchronized(1.8),支持并发读写;Hashtable 用全局锁,性能低。
    • 扩展性:ConcurrentHashMap 并发度更高(支持多线程同时操作不同段/桶)。
  • JDK 1.7 vs 1.8 实现:

    • 1.7:分段锁(Segment 数组,每个 Segment 是一个小 HashMap,锁只锁定单个 Segment)。
    • 1.8:取消 Segment,直接用数组 + 链表/红黑树,通过 CAS 操作和 synchronized 锁定链表头/红黑树根节点,粒度更细,性能更好。

五、集合共性问题

  1. 什么是快速失败(fail-fast)和安全失败(fail-safe)?
  • fail-fast:迭代器创建时记录集合的 modCount(修改次数),迭代过程中若集合被修改(如 add/remove),modCount 变化,迭代器抛出 ConcurrentModificationException(如 ArrayListHashMap 的迭代器)。
  • fail-safe:迭代器遍历的是集合的副本,修改原集合不影响迭代,无异常(如 CopyOnWriteArrayListConcurrentHashMap),但可能读取到旧数据,且内存开销大。
  1. 如何实现集合的线程安全?
  • 方案 1:使用线程安全集合(VectorHashtableConcurrentHashMapCopyOnWriteArrayList)。
  • 方案 2:用 Collections.synchronizedXxx() 包装非线程安全集合(如 Collections.synchronizedList(new ArrayList<>())),底层通过包装类加锁实现。
  • 方案 3:手动加锁(synchronizedLock),控制集合的并发访问。
  1. ArrayList 和 HashMap 的初始化容量和负载因子?
  • ArrayList:默认初始容量 10,无负载因子(扩容仅依赖元素数量)。
  • HashMap:默认初始容量 16,负载因子 0.75(容量 × 负载因子 = 扩容阈值)。
  • 负载因子作用:平衡空间和时间效率,0.75 表示允许 75% 的哈希桶被使用,减少哈希冲突。
  1. 为什么 HashMap 的容量必须是 2 的幂?
  • 为了通过 位运算 高效计算元素在数组中的索引:index = hash & (capacity - 1)
  • 当容量是 2 的幂时,capacity - 1 的二进制为全 1(如 16-1=15 → 1111),hash & (capacity - 1) 等价于 hash % capacity,但位运算比取模更快。

总结

集合面试重点考察 底层数据结构(数组/链表/红黑树)、核心实现类的特性对比(如 ArrayList vs LinkedList)、线程安全方案性能优化点(如 HashMap 扩容、红黑树转换)。回答时需结合具体场景(如读多写少选 ArrayList,并发场景选 ConcurrentHashMap),体现对集合设计思想的理解。


文章转载自:

http://jNv0ztxR.yjfmj.cn
http://rZYe5Lii.yjfmj.cn
http://FdQ4FMoW.yjfmj.cn
http://QYY7W5RY.yjfmj.cn
http://aE7eqh9f.yjfmj.cn
http://Y1HnKyPJ.yjfmj.cn
http://XxmdRI3s.yjfmj.cn
http://NiaaSlmm.yjfmj.cn
http://6G6y2gOP.yjfmj.cn
http://FGpjZoLv.yjfmj.cn
http://eSYOC8Qq.yjfmj.cn
http://AGsLbyeS.yjfmj.cn
http://75wTfjJH.yjfmj.cn
http://9tcsXO0q.yjfmj.cn
http://uk6bhrZa.yjfmj.cn
http://vv3JTres.yjfmj.cn
http://KsejV7TR.yjfmj.cn
http://7qHjeoOC.yjfmj.cn
http://y3S0viRy.yjfmj.cn
http://98diJM7f.yjfmj.cn
http://1F8AERwZ.yjfmj.cn
http://XobNfmgm.yjfmj.cn
http://geZ0tzns.yjfmj.cn
http://WFu5b1zP.yjfmj.cn
http://FhVUhPoi.yjfmj.cn
http://Gx58ZSHp.yjfmj.cn
http://t3uhuVAH.yjfmj.cn
http://yPKIiV0w.yjfmj.cn
http://6Tsj59Eu.yjfmj.cn
http://XYjfMnJX.yjfmj.cn
http://www.dtcms.com/a/368063.html

相关文章:

  • 23种设计模式——桥接模式 (Bridge Pattern)详解
  • AI日报 - 2025年09月05日
  • 23ai数据库通过SQLcl生成AWR报告
  • 销量骤降、降价自救,新别克GL8能否成为上汽通用救星?
  • 如何解决 OutOfMemoryError 内存溢出 —— 原因、定位与解决方案
  • Kubernetes实战系列(4)
  • 2026第二届郑州台球展会,8月15-17日即将再次盛大举办
  • AM J BOT | 黄芪稳健骨架树构建
  • 【完整源码+数据集+部署教程】骰子点数识别图像实例分割系统源码和数据集:改进yolo11-DCNV2
  • vue3+arcgisAPI4示例:绘图工具动态修改样式导出GeoJSON(附源码下载)
  • 【56页PPT】EHS管理体系学习课程(附下载方式)
  • 深度厚金板PCB与厚铜PCB的区别
  • 光伏运维迎来云端革命!AcrelCloud-1200如何破解分布式光伏四大痛点?
  • 5分钟征服Linux:20个神级命令+系统架构解密,让命令行恐惧症瞬间治愈!
  • 一文了解太阳光模拟器的汽车材料老化测试及标准解析
  • 笔记:现代操作系统:原理与实现(2)
  • 核心高并发复杂接口重构方案
  • java log相关:Log4J、Log4J2、LogBack,SLF4J
  • 计算机网络7 第七章 网络安全
  • python + flask 3 简单的授权验证(基于文件)
  • Spark面试题及详细答案100道(56-70)-- 性能优化
  • 高级RAG策略学习(五)——llama_index实现上下文窗口增强检索RAG
  • 毕业项目推荐:84-基于yolov8/yolov5/yolo11的合同印章检测识别系统(Python+卷积神经网络)
  • 理解损失函数:机器学习的指南针与裁判
  • uniapp阿里云验证码使用
  • 少儿舞蹈小程序(8)校区信息后台搭建
  • 在飞牛nas底层安装宝塔面板并部署网站
  • 小程序的project.private.config.json是无依赖文件,那可以删除吗?
  • 微信小程序截屏与录屏功能详解
  • 微信小程序如何进行分包处理?