Java集合框架

两大支线:Collection和Map:

1、Collection,主要由List、Set、Queue组成:

  • List 代表有序、可重复的集合,典型代表有封装动态数组的 ArrayList 和 封装链表的 LinkedList;
  • Set 代表无序、不可重复的集合,典型代表有 TreeSet 和 HashSet;
  • Queue 代表先进先出(FIFO)的队列,典型代表就是双端队列 ArrayDeque 和优先级队列 PriorityQueue。

2、Map,代表键值对(key-value)的集合,典型代表就是 HashMap、LinkedHashMap。

接口特点实现类
List (列表)有序、可重复ArrayList、LinkedList
Set(集合)无序、不可重复HashSet、TreeSet
Queue(队列)保持元素队列PriorityQueue、ArrayDeque
Map(映射)键值对:一个键映射到一个值HashMap、LinkedHashMap

List

List 有 ArrayList 和 LinkedList 两个代表,关于这两个的叙述在前文有提及:ArrayList 和 LInkedList 的区别


Set

在 Java 中,TreeSetHashSet 都是 Set 接口的实现类,主要用于存储 不重复 的元素。但它们的底层实现、排序方式以及性能差异较大。

TreeSet:

特点:

  1. 基于红黑树(Red-Black Tree)实现,底层使用 TreeMap 维护元素的顺序。
  2. 元素是有序的,默认按照 自然顺序(Comparable) 排序,或者根据自定义的 Comparator 进行排序。
  3. 查找、插入、删除的时间复杂度为 O(log N),比 HashSet 慢,但能保证顺序。
顺便在此补充一下红黑树是什么:

红黑树(Red-Black Tree)

红黑树是一种 自平衡二叉搜索树(Balanced Binary Search Tree),用于保持数据的有序性,并在插入、删除操作后维持 近似平衡,避免二叉搜索树退化成链表。

红黑树的特性

红黑树满足以下 五大特性

  1. 每个节点要么是红色,要么是黑色
  2. 根节点始终是黑色
  3. 红色节点的子节点必须是黑色(即 不能有连续的红色节点)。
  4. 从任意一个节点到其所有叶子节点的路径中,黑色节点的数量必须相同(即 黑色平衡)。
  5. 新插入的节点默认为红色
    红黑树示例

TreeSet 使用示例

import java.util.TreeSet;

public class TreeSetExample {
    public static void main(String[] args) {
        TreeSet<Integer> treeSet = new TreeSet<>();
        treeSet.add(10);
        treeSet.add(5);
        treeSet.add(20);
        treeSet.add(15);

        System.out.println(treeSet); // [5, 10, 15, 20] 按照升序排列
    }
}

适用场景

  • 需要 排序 的场景,例如:存储排名、时间戳、字典排序等。
  • 需要 范围查找 的场景,例如 headSet()tailSet()subSet() 方法,能快速查找区间数据。

HashSet

特点

  1. 基于 HashMap 实现,底层使用 HashMap 存储元素。
  2. 元素是无序的,存储顺序可能会随哈希值的变化而改变。
  3. 查找、插入、删除的时间复杂度为 O(1)(在哈希冲突少的情况下),比 TreeSet 更快。

使用示例

import java.util.HashSet;

public class HashSetExample {
    public static void main(String[] args) {
        HashSet<Integer> hashSet = new HashSet<>();
        hashSet.add(10);
        hashSet.add(5);
        hashSet.add(20);
        hashSet.add(15);

        System.out.println(hashSet); // [20, 5, 10, 15] 取决于 hash 值的计算:hash % 16 
    }
}

适用场景

  • 去重但不关心顺序 的场景,例如存储用户 ID、缓存数据等。
  • 插入和查找速度要求快,比如 集合操作、统计唯一值等

TreeSet vs HashSet 区别对比

对比项TreeSetHashSet
底层数据结构红黑树(TreeMap)哈希表(HashMap)
排序有序(按照自然顺序或 Comparator)无序
增删改查时间复杂度O(log N)O(1)(哈希冲突少时)
适合场景需要排序、范围查询插入/查找快,不关心顺序
内存消耗较大(存储树结构)较小

什么时候用 TreeSet?什么时候用 HashSet?

  • 如果需要排序(如按字母、时间、数值等),用 TreeSet
  • 如果不关心顺序,只是要存储不重复的元素,并且查找速度要求快,用 HashSet

Queue

1. Queue 概述

Queue(队列)是 Java 集合框架 (java.util.Queue 接口) 中的一种 FIFO(First In First Out,先进先出) 数据结构,主要用于 存储等待处理的元素,常用于任务调度、消息队列等场景。其代表包括 PriorityQueue(优先级队列) 和 ArrayDeque(双端队列)。

1. PriorityQueue(优先级队列)

概述
  • PriorityQueue基于堆(Heap) 实现的 优先级队列,元素按照 自然顺序自定义比较规则 进行排序。
  • 默认是最小堆(最小元素优先出队),也可以自定义比较器改为最大堆。
  • 不允许存 null不保证插入顺序,但 保证元素出队时是有序的
    在这里插入图片描述
底层实现
  • 使用 二叉堆(最小堆),默认 数组存储(默认初始容量 11)。
  • 通过 上浮(siftUp)和下沉(siftDown) 操作维持堆结构。
  • 时间复杂度
    • 入队(offer:O(log N)
    • 出队(poll:O(log N)
    • 查看队头(peek:O(1)
代码示例
import java.util.PriorityQueue;

public class PriorityQueueExample {
    public static void main(String[] args) {
        PriorityQueue<Integer> pq = new PriorityQueue<>();

        pq.offer(30);
        pq.offer(10);
        pq.offer(20);

        System.out.println("队列内容:" + pq); // 输出无序,但出队有序
        while (!pq.isEmpty()) {
            System.out.println("出队:" + pq.poll());
        }
    }
}

输出

队列内容:[10, 30, 20]
出队:10
出队:20
出队:30
应用场景
  • 任务调度(如 CPU 任务管理)
  • 最短路径算法(如 Dijkstra)
  • 高频元素统计(如 Top K 问题)

2. ArrayDeque(数组双端队列)

概述
  • ArrayDeque双端队列(Deque)数组实现,支持 队列(FIFO)和栈(LIFO) 两种用法。
  • LinkedList 更快,因为 LinkedList 需要维护额外的指针,而 ArrayDeque 直接操作数组。
  • 无界(但实际受 Integer.MAX_VALUE 限制)。
  • 不允许存 null
    在这里插入图片描述
底层实现
  • **使用 Object[] 数组 存储元素,采用循环数组(避免扩容时数据搬移)。
  • 默认初始容量 16,满时 扩容为 2 倍
  • 时间复杂度
    • 入队/出队(offerFirstpollFirstofferLastpollLast:O(1)
    • 扩容时:O(N)
代码示例
import java.util.ArrayDeque;

public class ArrayDequeExample {
    public static void main(String[] args) {
        ArrayDeque<Integer> deque = new ArrayDeque<>();

        // 从队尾添加
        deque.offerLast(1);
        deque.offerLast(2);
        deque.offerLast(3);

        System.out.println("队列:" + deque); // [1, 2, 3]

        // 从队头取出
        System.out.println("出队:" + deque.pollFirst()); // 1

        // 栈用法(先进后出)
        deque.push(10);
        System.out.println("栈顶元素:" + deque.peek()); // 10
    }
}
应用场景
  • 高效队列实现(比 LinkedList 性能更优)
  • 双端操作(如滑动窗口问题)
  • 实现栈(替代 Stack 类)

3. PriorityQueue vs ArrayDeque

对比项PriorityQueue(优先级队列)ArrayDeque(双端队列)
数据结构二叉堆(最小堆或最大堆)循环数组
插入顺序无序(内部排序)有序(FIFO 或 LIFO)
取出顺序按优先级取出按插入顺序取出
时间复杂度O(log N)(插入、删除)O(1)(插入、删除)
是否允许 null❌ 否❌ 否
使用场景任务调度、最短路径算法队列、栈、滑动窗口

Map

Map 介绍

Map 是 Java 中用于存储键值对 (key-value) 的数据结构,每个键唯一映射到一个值。常见的 Map 实现包括 HashMapLinkedHashMap,它们在存储方式、访问效率、是否保持插入顺序等方面有所不同。


1. HashMap

特点
  • 基于哈希表实现,存储的是 键值对
  • 无序,不能保证插入顺序。
  • 允许 null 作为键和值。
  • 线程不安全,多个线程同时修改 HashMap 可能导致数据不一致(可以使用 Collections.synchronizedMap()ConcurrentHashMap)。
  • 采用 拉链法 解决哈希冲突,JDK 1.8 之后引入红黑树优化
    在这里插入图片描述
底层实现
  • 采用 数组 + 链表/红黑树 结构存储数据。
  • 哈希计算key.hashCode() 计算哈希值后,通过 (n - 1) & hash 确定数组索引
  • 扩容机制:默认 容量 16,负载因子 0.75,当超过容量的 75% 时扩容为 2 倍
  • 红黑树优化:当链表长度超过 8,转换为红黑树,提高查找效率。

2. LinkedHashMap(添加链表使得 HashMap 有序)

特点
  • 有序,按照 插入顺序 或 LRU(最近最少使用)顺序 进行存储。
  • 继承自 HashMap在 HashMap 的基础上增加了双向链表,以维护元素顺序。
  • 允许 null 作为键和值。
  • 性能略低于 HashMap,因为需要维护链表结构。
  • 适用于缓存场景(如 LRU 缓存)
    在这里插入图片描述
底层实现
  • 继承 HashMap,但在每个节点中额外维护了一个双向链表,用于记录元素的插入顺序或访问顺序(LRU)。
  • 扩展了 Entry 结构,新增了 beforeafter 指针:
    static class Entry<K,V> extends HashMap.Node<K,V> {
        Entry<K,V> before, after;
    }
    
  • 通过 accessOrder 决定顺序:
    • false(默认):保持 插入顺序
    • true(LRU):每次访问都会将节点移动到队尾,形成 最近最少使用淘汰策略

总结

  • HashMap:基于哈希表,无序存储,查找快(O(1))
  • LinkedHashMap:继承自 HashMap有序存储,适用于缓存(LRU)场景

你可以在高性能存储或缓存设计中选择合适的 Map,如果需要维持顺序或 LRU 淘汰机制,推荐使用 LinkedHashMap

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值