Java面试题5:List、Set、Map 的区别?各自有哪些实现类?

核心区别

  1. List (列表)
    • 核心特性:有序集合,允许重复元素。
    • 行为: 用户可以根据元素的整数索引(位置)访问元素。可以精确控制每个元素在列表中的位置。支持在指定位置插入和删除元素。
    • 典型实现: ArrayList, LinkedList, Vector
  2. Set (集合)
    • 核心特性:无序集合,不允许重复元素(唯一性)。
    • 行为: 不保证元素的顺序(某些特定实现如 LinkedHashSetTreeSet 会维护某种顺序)。最重要的操作是检查一个元素是否存在于集合中(contains)。
    • 典型实现: HashSet, LinkedHashSet, TreeSet
  3. Map (映射)
    • 核心特性:键值对(Key-Value Pair)的集合。键(Key)唯一,值(Value)可重复。
    • 行为: 通过键来访问值。一个映射不能包含重复的键。每个键最多只能映射到一个值。
    • 典型实现: HashMap, LinkedHashMap, TreeMap, Hashtable

简单对比表:

接口 元素特性 顺序保证 元素唯一性 访问方式
List 单个对象 有序 可重复 索引 (get(int))
Set 单个对象 无序 唯一 元素本身
Map 键值对 (K, V) 键无序/有序 键唯一 键 (get(K))

主要实现类

  1. List 实现类
    • ArrayList
      • 底层: 基于动态数组实现。
      • 特点:
        • 支持随机访问(通过索引快速访问元素,时间复杂度 O(1))。
        • 在列表尾部插入和删除元素效率较高(接近 O(1))。
        • 在列表中间插入和删除元素效率较低(需要移动元素,时间复杂度 O(n))。
        • 非线程安全
    • LinkedList
      • 底层: 基于双向链表实现。
      • 特点:
        • 不支持高效的随机访问(需要遍历链表,时间复杂度 O(n))。
        • 任意位置插入和删除元素效率较高(时间复杂度 O(1),只需修改节点指针)。
        • 实现了 Deque 接口,可用作队列或双端队列。
        • 非线程安全
    • Vector
      • 底层: 基于动态数组实现。
      • 特点:
        • 是 Java 早期集合类。
        • 所有方法默认使用 synchronized 修饰,是线程安全的。
        • 性能通常不如 ArrayList(因为同步开销)。
        • 有一个子类 Stack(栈)。
  2. Set 实现类
    • HashSet
      • 底层: 基于 HashMap 实现(值存储在一个 HashMap 的键上)。
      • 特点:
        • 无序(不保证迭代顺序)。
        • 添加、删除、判断元素是否存在(contains)效率很高(时间复杂度接近 O(1))。
        • 非线程安全
    • LinkedHashSet
      • 底层: 继承自 HashSet,内部使用 LinkedHashMap 实现。
      • 特点:
        • 维护了一个双向链表来记录元素的插入顺序。
        • 迭代时按照元素的插入顺序访问。
        • 性能略低于 HashSet(因为要维护链表)。
        • 非线程安全
    • TreeSet
      • 底层: 基于 TreeMap 实现(值存储在一个 TreeMap 的键上)。
      • 特点:
        • 元素会根据自然排序指定的 Comparator 进行排序。
        • 迭代时按照排序后的顺序访问。
        • 添加、删除、判断元素是否存在(contains)基于红黑树,时间复杂度为 O(\\log n)
        • 非线程安全
  3. Map 实现类
    • HashMap
      • 底层: 基于哈希表(数组+链表/红黑树)实现。
      • 特点:
        • 键无序(不保证迭代顺序)。
        • 添加、删除、获取键值对效率很高(时间复杂度接近 O(1))。
        • 允许 null 作为键和值。
        • 非线程安全
      • 重要: JDK 1.8 引入了链表长度超过阈值转红黑树的优化。
    • LinkedHashMap
      • 底层: 继承自 HashMap,内部维护了一个双向链表
      • 特点:
        • 可以维护键的插入顺序访问顺序(LRU 缓存常用)。
        • 迭代时按照链表的顺序访问(插入顺序或访问顺序)。
        • 性能略低于 HashMap(因为要维护链表)。
        • 非线程安全
    • TreeMap
      • 底层: 基于红黑树(一种自平衡二叉搜索树)实现。
      • 特点:
        • 键会根据自然排序指定的 Comparator 进行排序。
        • 迭代时按照键排序后的顺序访问。
        • 添加、删除、获取键值对基于红黑树,时间复杂度为 O(\\log n)
        • 不允许 null 作为键(如果使用自然排序)。
        • 非线程安全
    • Hashtable
      • 底层: 基于哈希表实现。
      • 特点:
        • 是 Java 早期集合类,与 Vector 类似。
        • 所有方法默认使用 synchronized 修饰,是线程安全的。
        • 性能通常不如 HashMap(因为同步开销)。
        • 不允许 null 作为键或值
        • 现在通常更推荐使用 ConcurrentHashMap 替代它来实现线程安全。

线程安全注意事项

  • ArrayList, LinkedList, HashSet, LinkedHashSet, TreeSet, HashMap, LinkedHashMap, TreeMap 都是非线程安全的。
  • Vector, Hashtable线程安全的(但通常性能较低)。
  • 对于 ListSet,可以使用 Collections.synchronizedList()Collections.synchronizedSet() 包装非线程安全的集合来获得线程安全版本。
  • 对于 Map,可以使用 Collections.synchronizedMap() 包装非线程安全的 Map,或者更推荐使用 ConcurrentHashMap(它是专门设计的高并发 Map 实现)。
相关推荐
咩咩啃树皮10 小时前
第40篇:Vue3组件化开发精讲——组件拆分、复用、父子通信、工程化架构
java·前端·架构
灯澜忆梦11 小时前
GO_并发编程---定时器
开发语言·后端·golang
鱟鲥鳚11 小时前
Spring Boot 集成 LangChain4j:从模型调用到 Tool Calling(Demo版)
java·spring boot
-银雾鸢尾-11 小时前
C#中的StringBuilder相关方法
开发语言·c#
-银雾鸢尾-11 小时前
C#中结构体与类的区别;抽象类与接口的区别
开发语言·c#
大模型码小白12 小时前
【Python零基础教程】继承、多态与魔法函数:面向对象编程三大核心特性详解
java·大数据·开发语言·人工智能·python·ai编程
腾渊信息科技公司13 小时前
Spring Boot对接MES实战:视觉检测数据自动同步方案
java·人工智能·spring boot·后端·计算机视觉·ai·软件需求
爱笑的源码基地14 小时前
高并发 Redis 缓存门诊HIS系统源码,含财务统计药房进销存
java·程序·门诊系统·诊所系统·云诊所源码
wuqingshun31415914 小时前
TCP超时重传机制是为了解决什么问题?
java
段一凡-华北理工大学14 小时前
向量数据库实战:选型、调优与落地~系列文章12:文本分块策略实战:chunk_size 怎么选?重叠多少?
开发语言·数据库·后端·oracle·rust·工业智能体·高炉智能化