Java 中常用的数据结构实现类主要集中在 java.util 包下,基于 Collection 和 Map 两大核心接口展开,不同实现类在底层结构、线程安全性、增删改查效率上有显著差异,以下从核心分类、底层原理、适用场景等角度进行全面梳理。
一、 线性表相关实现类
线性表是最基础的有序数据结构,元素按顺序存储,支持按索引访问,核心实现类包括 ArrayList 、 LinkedList 和 Vector 。
- ArrayList
底层基于动态扩容的 Object 数组实现,默认初始容量为 10,当元素数量达到容量上限时,会按照 1.5 倍的比例扩容(创建新数组并拷贝原数组元素)。它的优势在于随机访问效率高(通过索引直接定位,时间复杂度 O(1)),但在数组头部或中间插入、删除元素时效率较低(需要移动后续元素,时间复杂度 O(n))。 ArrayList 是非线程安全的,适合读多写少、需要频繁随机访问的场景。
- LinkedList
底层基于双向链表实现,每个节点包含前驱节点引用、后继节点引用和元素值,不存在扩容问题。它的优势在于头尾插入、删除效率高(无需移动元素,时间复杂度 O(1)),但随机访问效率低(需要从表头或表尾遍历到目标索引,时间复杂度 O(n))。 LinkedList 同时实现了 Deque 接口,可作为栈、队列或双端队列使用,同样是非线程安全的,适合频繁在首尾操作元素的场景。
- Vector
底层同样基于动态扩容的 Object 数组实现,与 ArrayList 原理类似,但它是线程安全的------其核心方法(如 add 、 get )都使用 synchronized 关键字修饰。不过, Vector 的扩容比例是 2 倍,且由于锁的粒度较粗,并发效率较低,现在已逐渐被 CopyOnWriteArrayList 替代,仅在遗留代码中常见。
二、 集合相关实现类
集合的核心特性是元素不重复,底层依赖哈希表或红黑树实现,核心实现类包括 HashSet 、 LinkedHashSet 和 TreeSet 。
- HashSet
底层基于 HashMap 实现(利用 HashMap 的 key 存储元素,value 固定为一个静态空对象),元素的存储顺序不保证有序,取决于元素的哈希值和数组长度。它的增删查效率都很高(时间复杂度 O(1)),但需要元素正确重写 hashCode() 和 equals() 方法------否则会导致重复元素无法被正确识别。 HashSet 是非线程安全的,适合不需要有序存储、追求高效存取的去重场景。
- LinkedHashSet
底层基于 LinkedHashMap 实现,在 HashMap 的基础上维护了一个双向链表,用于记录元素的插入顺序。因此它既具备 HashSet 的高效存取特性,又能保证元素按插入顺序遍历,同样需要元素重写 hashCode() 和 equals() 方法,非线程安全,适合需要有序去重的场景。
- TreeSet
底层基于 TreeMap 实现(利用 TreeMap 的 key 存储元素),底层数据结构为红黑树,能够自动对元素进行升序排序(默认按自然顺序,也可通过构造方法传入 Comparator 自定义排序规则)。它的增删查效率为 O(log n),元素必须实现 Comparable 接口(或自定义比较器),否则会抛出 ClassCastException 。 TreeSet 是非线程安全的,适合需要有序存储且支持范围查询的去重场景。
三、 映射相关实现类
映射(键值对结构)的核心是键唯一,值可重复,核心实现类包括 HashMap 、 LinkedHashMap 、 TreeMap 和 Hashtable 。
- HashMap
底层在 JDK 1.8 后采用 "数组 + 链表 + 红黑树" 的混合结构:数组是主体,当链表长度超过阈值(默认 8)且数组长度大于等于 64 时,链表会转为红黑树,以提升查询效率。它的键不保证有序,允许键和值为 null (但键只能有一个 null ),增删查效率为 O(1)。 HashMap 是非线程安全的,是日常开发中最常用的映射实现类,适合追求高效存取、不要求有序的键值对场景。
- LinkedHashMap
继承自 HashMap ,底层在 HashMap 结构基础上维护了一个双向链表,用于记录键值对的插入顺序或访问顺序(通过构造方法的 accessOrder 参数控制)。它的存取效率略低于 HashMap,但能保证遍历顺序,允许键和值为 null ,非线程安全,适合需要按插入/访问顺序遍历键值对的场景。
- TreeMap
底层基于红黑树实现,键会自动按自然顺序或自定义比较器顺序排序,不允许键为 null (否则会抛出 NullPointerException ),值可以为 null 。它支持范围查询(如 subMap 、 headMap 方法),增删查效率为 O(log n),键必须实现 Comparable 接口或传入自定义 Comparator ,非线程安全,适合需要有序键值对且支持范围操作的场景。
- Hashtable
底层基于哈希表实现,是一个古老的映射实现类,线程安全(方法使用 synchronized 修饰),但不允许键和值为 null ,扩容比例为 2 倍,并发效率较低。现在已被 ConcurrentHashMap 替代,仅在遗留代码中可见。
- ConcurrentHashMap
是 HashMap 的线程安全版本,底层在 JDK 1.8 后采用 "数组 + 链表 + 红黑树" 结构,通过 CAS 操作 + synchronized 分段锁 实现线程安全,锁的粒度更细,并发效率远高于 Hashtable 和 Vector 。它不允许键为 null ,适合高并发场景下的键值对存储。
四、 队列/双端队列相关实现类
队列遵循 FIFO(先进先出) 原则,双端队列支持头尾两端操作,核心实现类包括 ArrayDeque 、 LinkedList 和 PriorityQueue 。
- ArrayDeque
底层基于动态扩容的循环数组实现,是双端队列的高效实现,不允许存储 null 元素。它的头尾插入、删除效率为 O(1),随机访问效率高,非线程安全,可作为栈(比 Stack 高效)或队列使用,适合频繁首尾操作的场景。
- LinkedList
作为双端队列时,底层双向链表结构支持头尾元素的快速操作,允许存储 null 元素,非线程安全,适合需要灵活操作首尾元素的场景。
- PriorityQueue
底层基于优先堆(小顶堆)实现,队列中的元素会自动按自然顺序或自定义比较器排序,不允许存储 null 元素,非线程安全。它的出队操作会返回优先级最高的元素,适合需要按优先级处理任务的场景。