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

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://www.xdnf.cn/news/20359.html

相关文章:

  • GigaDevice(兆易创新)GD25Q64CSJGR 64Mbit FLASH
  • c#动态树形表达式详解
  • uni-app 和 uni-app x 的区别
  • 【Cell Systems】SpotGF空间转录组去噪算法文献分享
  • 图像去雾:从暗通道先验到可学习融合——一份可跑的 PyTorch 教程
  • <video> 标签基础用法
  • MySQL-安装MySQL
  • UE4 Mac构建编译报错 no template named “is_void_v” in namespace “std”
  • 无需bootloader,BootROM -> Linux Kernel 启动模式
  • Java全栈开发工程师面试实录:从基础到实战的深度探讨
  • PyTorch图像数据转换为张量(Tensor)并进行归一化的标准操作
  • 管理中心理学问:动机与管理的关联
  • 什么是CRM?定义、作用、功能、选型|CRM百科
  • 使用若依加Trae快速搭建一对儿多对多CRUD
  • 移植Qt4.8.7到ARM40-A5
  • PiscCode基于 Mediapipe 实现轨迹跟踪
  • TOGAF之架构标准规范-迁移计划
  • nginx 反向代理使用变量的坑
  • 亚马逊商品转化率怎么提高?从传统运营到智能广告的系统化突破
  • Nginx 配置片段主要用于实现​​正向代理​​,可以用来转发 HTTP 和 HTTPS 请求
  • LangChain关于提示词的几种写法
  • 深度学习:Dropout 技术
  • c++ 第三方库与个人封装库
  • 【完整源码+数据集+部署教程】西兰花实例分割系统源码和数据集:改进yolo11-AggregatedAtt
  • leetcode 6 Z字形变化
  • 基于YOLOv8的车辆轨迹识别与目标检测研究分析软件源代码+详细文档
  • 整理了几道前端面试题
  • 字符串格式化——`vsnprintf`函数
  • 图像处理:实现多图点重叠效果
  • More Effective C++ 条款29:引用计数