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 实现)。
相关推荐
编程探索者小陈9 小时前
接口自动化三件套:JSON Schema 校验 + logging 日志 + Allure 测试报告
开发语言·python
星恒随风9 小时前
C++ 类和对象入门(二):默认成员函数、构造函数和析构函数详解
开发语言·c++·笔记·学习
摇滚侠9 小时前
JavaWeb 全套教程 乱码问题 85-88
java·开发语言
问心无愧05139 小时前
ctf show web入门102
android·java·前端·笔记
San813_LDD9 小时前
[量化]《虚函数调用时间复杂度完全解析:为什么是 O(1) 以及它的真实代价》
java·数据结构·算法
武子康10 小时前
Java-19 深入浅出MyBatis 代理模式:从 Java 动态代理到 Mapper 接口的底层原理
java·后端
devilnumber10 小时前
Java Lambda方法引用的三类核心类型、转化逻辑与深度对比
java·开发语言
郑洁文10 小时前
基于Springboot的足球青训俱乐部管理系统的设计与实现
java·spring boot·后端·足球青训俱乐部管理系统
geminigoth10 小时前
python入门三:字典、输入、while循环
开发语言·python
牛油果子哥q10 小时前
【C++ this指针】C++ this指针深度精讲:this底层本质、存储位置、调用机制、const this指针、空指针调用、面试坑点与工程实战
开发语言·c++·面试