目录
- 一、集合框架层次结构
- 二、Collection集合
- 1、Queue队列
- 1. LinkedList 作为队列
- 2. ArrayDeque 作为队列
- 3. PriorityQueue 优先队列
- 4.LinkedBlockingQueue - 最常用的阻塞队列
- 5. ConcurrentLinkedQueue - 高并发非阻塞队列
- 2、队列操作模式对比
- 1.插入操作对比
- 2.移除操作对比
- 3.查看操作对比
- 3、队列选择
Java 集合框架(Collections Framework)是 Java 中用于存储和操作数据组的重要架构。它提供了一组接口、实现类和算法。
一、集合框架层次结构
Collection (接口) ├── List (接口 - 有序,可重复) │ ├── ArrayList (实现类) │ ├── LinkedList (实现类) │ ├── Vector (线程安全,已过时) │ └── Stack (继承Vector) │ ├── Set (接口 - 无序,不可重复) │ ├── HashSet (实现类) │ │ └── LinkedHashSet (保持插入顺序) │ ├── SortedSet (接口) │ │ └── TreeSet (实现类) │ └── EnumSet (专用于枚举) │ └── Queue (接口 - 队列) ├── Deque (双端队列接口) │ ├── ArrayDeque (实现类) │ └── LinkedList (也实现了Deque) │ ├── PriorityQueue (优先队列) └── BlockingQueue (阻塞队列接口) ├── ArrayBlockingQueue ├── LinkedBlockingQueue └── PriorityBlockingQueue Map (接口 - 键值对) ├── HashMap (实现类) │ └── LinkedHashMap (保持插入顺序) ├── TreeMap (基于红黑树) ├── Hashtable (线程安全,已过时) ├── WeakHashMap (弱引用) └── ConcurrentHashMap (并发版)Java集合大致可以分为两大体系,一个是Collection,另一个是Map
Collection:主要由List、Set、Queue接口组成,List代表有序、重复的集合;其中Set代表无序、不可重复的集合;Queue体系集合,代表一种队列集合实现。Map:则代表具有映射关系的键值对集合。
java.util.Collection下的接口和继承类关系简易结构图:
java.util.Map下的接口和继承类关系简易结构图:
其中,Java 集合框架中主要封装的是典型的数据结构和算法,如动态数组、双向链表、队列、栈、Set、Map等。
二、Collection集合
通过集合的关系图我们可以知道Collection是集合的顶层父类,他定义了集合的基本方法如
基本操作方法
| 方法签名 | 功能描述 | 返回值 | 示例 | 时间复杂度 |
|---|---|---|---|---|
int size() | 返回集合中元素的数量 | 元素个数 | list.size()→3 | O(1) |
boolean isEmpty() | 判断集合是否为空 | true/false | list.isEmpty()→false | O(1) |
boolean contains(Object o) | 判断是否包含指定元素 | true/false | list.contains("A")→true | List: O(n) Set: O(1) TreeSet: O(log n) |
boolean add(E e) | 添加元素到集合 | 是否成功 | list.add("D")→true | ArrayList: 均摊O(1) LinkedList: O(1) TreeSet: O(log n) |
boolean remove(Object o) | 移除指定元素 | 是否成功 | list.remove("A")→true | ArrayList: O(n) LinkedList: O(n) HashSet: O(1) |
批量操作方法
| 方法签名 | 功能描述 | 返回值 | 示例 | 说明 |
|---|---|---|---|---|
boolean containsAll(Collection<?> c) | 是否包含集合c中所有元素 | true/false | list.containsAll(subList) | 检查子集关系 |
boolean addAll(Collection<? extends E> c) | 添加集合c中所有元素 | 是否改变 | list.addAll(anotherList) | 批量添加 |
boolean removeAll(Collection<?> c) | 移除集合c中所有元素 | 是否改变 | list.removeAll(toRemove) | 差集操作 |
boolean retainAll(Collection<?> c) | 仅保留集合c中元素 | 是否改变 | list.retainAll(common) | 交集操作 |
void clear() | 清空集合所有元素 | 无 | list.clear() | 集合变为空 |
转换和迭代方法
| 方法签名 | 功能描述 | 返回值 | 示例 | 说明 |
|---|---|---|---|---|
Object[] toArray() | 转换为Object数组 | Object数组 | list.toArray() | 返回新数组 |
<T> T[] toArray(T[] a) | 转换为指定类型数组 | 指定类型数组 | list.toArray(new String[0]) | 类型安全转换 |
Iterator<E> iterator() | 返回迭代器 | Iterator对象 | list.iterator() | 用于遍历集合 |
default boolean removeIf(Predicate<? super E> filter) | 条件删除 | 是否改变 | list.removeIf(s -> s.length() > 3) | Java 8+ |
default Spliterator<E> spliterator() | 返回分割迭代器 | Spliterator对象 | list.spliterator() | Java 8+,并行遍历 |
default Stream<E> stream() | 返回顺序流 | Stream对象 | list.stream() | Java 8+,流操作 |
default Stream<E> parallelStream() | 返回并行流 | Stream对象 | list.parallelStream() | Java 8+,并行流操作 |
集合运算方法
| 方法 | 数学运算 | 示意图 | 示例 |
|---|---|---|---|
addAll() | 并集 | A ∪ B | A.addAll(B) |
retainAll() | 交集 | A ∩ B | A.retainAll(B) |
removeAll() | 差集 | A - B | A.removeAll(B) |
常见操作示例
| 操作需求 | 代码示例 | 说明 |
|---|---|---|
| 遍历集合 | for (E e : collection) { ... } | 增强for循环 |
| 安全遍历并删除 | iterator.remove() | 使用迭代器删除 |
| 转换为数组 | String[] arr = coll.toArray(new String[0]) | 推荐写法 |
| 批量添加元素 | coll.addAll(Arrays.asList("A","B","C")) | 初始化集合 |
| 过滤集合 | coll.removeIf(e -> e.startsWith("A")) | Java 8+ |
| 集合判空 | if (!coll.isEmpty()) { ... } | 优于size() > 0 |
注意事项表格
| 方法 | 注意事项 | 推荐做法 |
|---|---|---|
| contains() | 依赖equals()和hashCode() | 正确实现这两个方法 |
| remove(Object) | 只删除第一个匹配项 | 使用removeIf()删除所有 |
| toArray() | 无参方法返回Object[] | 使用带参方法指定类型 |
| addAll() | 可能修改原集合 | 注意并发修改异常 |
| clear() | 不释放元素引用 | 大集合考虑设为null |
| iterator() | 遍历时不能修改集合 | 使用迭代器的remove() |
| 场景 | 建议 | 理由 |
|---|---|---|
| 频繁包含检查 | 使用HashSet | O(1)时间复杂度 |
| 频繁插入删除 | 使用LinkedList | 首尾操作O(1) |
| 随机访问 | 使用ArrayList | O(1)索引访问 |
| 需要排序 | 使用TreeSet | 自动维护顺序 |
| 线程安全 | 使用并发集合 | ConcurrentHashMap等 |
| 只读操作 | 使用不可变集合 | Collections.unmodifiableXXX() |
Collection集合中所包含的方法:
publicinterfaceCollection<E>extendsIterable<E>{// 基本操作方法intsize();booleanisEmpty();booleancontains(Objecto);booleanadd(Ee);booleanremove(Objecto);// 批量操作booleancontainsAll(Collection<?>c);booleanaddAll(Collection<?extendsE>c);booleanremoveAll(Collection<?>c);booleanretainAll(Collection<?>c);voidclear();// 数组转换Object[]toArray();<T>T[]toArray(T[]a);// 迭代器Iterator<E>iterator();// Java 8 新增方法defaultbooleanremoveIf(Predicate<?superE>filter){...}defaultSpliterator<E>spliterator(){...}defaultStream<E>stream(){...}defaultStream<E>parallelStream(){...}}1、Queue队列
核心概念Queue是 Java 集合框架中表示先进先出(FIFO)队列的接口,支持在队尾插入元素,在队头移除元素。
Queue 接口结构
publicinterfaceQueue<E>extendsCollection<E>{// 插入元素booleanadd(Ee);// 添加失败抛异常booleanoffer(Ee);// 添加失败返回false// 移除元素Eremove();// 移除失败抛异常Epoll();// 移除失败返回null// 查看元素(不移除)Eelement();// 查看失败抛异常Epeek();// 查看失败返回null}Queue 实现类对比
| 实现类 | 底层结构 | 线程安全 | 特性 | 使用场景 |
|---|---|---|---|---|
LinkedList | 双向链表 | ❌ 否 | 也可作List、Deque | 一般队列 |
ArrayDeque | 循环数组 | ❌ 否 | 高性能双端队列 | 推荐的单端队列 |
PriorityQueue | 二叉堆 | ❌ 否 | 优先级队列 | 任务调度 |
ArrayBlockingQueue | 数组 | ✅ 是 | 有界阻塞队列 | 生产者-消费者 |
LinkedBlockingQueue | 链表 | ✅ 是 | 可选有界阻塞队列 | 高并发队列 |
ConcurrentLinkedQueue | 链表 | ✅ 是 | 无锁队列 | 高并发非阻塞 |
PriorityBlockingQueue | 二叉堆 | ✅ 是 | 阻塞优先队列 | 优先级任务调度 |
DelayQueue | PriorityQueue | ✅ 是 | 延迟队列 | 定时任务 |
SynchronousQueue | 无存储 | ✅ 是 | 直接传递队列 | 线程间直接传递 |
1. LinkedList 作为队列
基本使用
// LinkedList 实现了 Queue 接口Queue<String>queue=newLinkedList<>();// 入队queue.offer("A");// 推荐使用 offer()queue.add("B");// 也可以使用 add()queue.offer("C");System.out.println(queue);// [A, B, C]// 查看队头Stringhead=queue.peek();// "A"(不移除)System.out.println("队头: "+head);// ASystem.out.println(queue);// [A, B, C](不变)// 出队Stringremoved1=queue.poll();// "A"Stringremoved2=queue.remove();// "B"(队列空时抛异常)System.out.println("出队后: "+queue);// [C]// 判断队列状态booleanisEmpty=queue.isEmpty();// falseintsize=queue.size();// 1特点
- 基于双向链表实现
- 可作队列、双端队列、列表使用
- 插入删除 O(1),查找 O(n)
- 非线程安全
使用场景
- 普通队列需求:消息队列、任务队列、等待队列
- 需要同时用到队列和列表功能
- 单线程环境或手动同步的多线程环境
2. ArrayDeque 作为队列
基本使用
// ArrayDeque 性能优于 LinkedListQueue<Integer>queue=newArrayDeque<>(10);// 指定初始容量// 入队for(inti=1;i<=5;i++){queue.offer(i);}// 遍历队列(不影响队列)System.out.print("队列元素: ");for(Integernum:queue){System.out.print(num+" ");// 1 2 3 4 5}System.out.println();// 批量出队while(!queue.isEmpty()){Integernum=queue.poll();System.out.println("处理: "+num);}特点
- 基于循环数组实现
- 性能比 LinkedList 好(内存连续)
- 初始容量为 16,自动扩容为 2 倍
- 推荐的单端队列实现
使用场景
- 高性能要求:游戏服务器、高频交易系统
- 已知容量上限:可以预分配合适大小
- 替代
Stack:使用ArrayDeque作为栈(push(), pop())
3. PriorityQueue 优先队列
基本使用
// 默认最小堆(小顶堆)Queue<Integer>pq=newPriorityQueue<>();// 添加元素pq.offer(5);pq.offer(1);pq.offer(3);pq.offer(8);pq.offer(2);// 按优先级出队(从小到大)while(!pq.isEmpty()){System.out.print(pq.poll()+" ");// 1 2 3 5 8}System.out.println();// 最大堆(大顶堆)Queue<Integer>maxHeap=newPriorityQueue<>(Comparator.reverseOrder());maxHeap.offer(5);maxHeap.offer(1);maxHeap.offer(3);while(!maxHeap.isEmpty()){System.out.print(maxHeap.poll()+" ");// 5 3 1}自定义排序
// 自定义对象优先队列classTaskimplementsComparable<Task>{Stringname;intpriority;// 数字越小优先级越高publicTask(Stringname,intpriority){this.name=name;this.priority=priority;}@OverridepublicintcompareTo(Taskother){returnInteger.compare(this.priority,other.priority);}@OverridepublicStringtoString(){returnname+"("+priority+")";}}Queue<Task>taskQueue=newPriorityQueue<>();taskQueue.offer(newTask("邮件",3));taskQueue.offer(newTask("电话",1));taskQueue.offer(newTask("会议",2));while(!taskQueue.isEmpty()){System.out.println(taskQueue.poll());// 电话(1) -> 会议(2) -> 邮件(3)}使用场景
- 任务调度:操作系统进程调度
- 医院急诊:按病情严重程度
- VIP服务:按会员等级
- 股票交易:按价格优先级
4.LinkedBlockingQueue - 最常用的阻塞队列
// 无界或有界阻塞队列BlockingQueue<Integer>queue=newLinkedBlockingQueue<>();// 无界BlockingQueue<Integer>boundedQueue=newLinkedBlockingQueue<>(100);// 有界// 生产者-消费者模式classProducerConsumer{privatefinalBlockingQueue<Integer>queue=newLinkedBlockingQueue<>(10);// 生产者classProducerimplementsRunnable{publicvoidrun(){try{for(inti=0;i<20;i++){queue.put(i);System.out.println("生产: "+i);Thread.sleep(100);}}catch(InterruptedExceptione){Thread.currentThread().interrupt();}}}// 消费者classConsumerimplementsRunnable{publicvoidrun(){try{while(true){Integeritem=queue.take();System.out.println("消费: "+item);Thread.sleep(150);}}catch(InterruptedExceptione){Thread.currentThread().interrupt();}}}}使用场景
- 线程池任务队列:
ThreadPoolExecutor默认使用 - 消息中间件:
Kafka、RocketMQ的生产者-消费者 - 日志处理:多个应用写日志,一个线程消费日志
- 数据缓冲:生产速度 > 消费速度时的缓冲
5. ConcurrentLinkedQueue - 高并发非阻塞队列
// 非阻塞并发队列ConcurrentLinkedQueue<String>concurrentQueue=newConcurrentLinkedQueue<>();// 多线程并发操作List<Thread>threads=newArrayList<>();// 生产者线程for(inti=0;i<5;i++){Threadproducer=newThread(()->{for(intj=0;j<10;j++){concurrentQueue.offer(Thread.currentThread().getName()+"-"+j);}});threads.add(producer);}// 消费者线程for(inti=0;i<3;i++){Threadconsumer=newThread(()->{while(!concurrentQueue.isEmpty()){Stringitem=concurrentQueue.poll();if(item!=null){System.out.println(Thread.currentThread().getName()+" 消费: "+item);}}});threads.add(consumer);}// 启动所有线程threads.forEach(Thread::start);threads.forEach(t->{try{t.join();}catch(InterruptedExceptione){}});System.out.println("最终队列大小: "+concurrentQueue.size());使用场景
- 实时日志收集:多个服务同时写日志
- 股票行情推送:高频行情数据
- 在线游戏:玩家动作队列
- 点击流分析:用户行为跟踪
2、队列操作模式对比
1.插入操作对比
Queue<String>queue=newLinkedList<>();// 插入方法对比queue.add("A");// 成功返回true,失败抛IllegalStateExceptionqueue.offer("B");// 成功返回true,失败返回false// 使用建议:// 1. 有界队列或不确定时用 offer()// 2. 确定不会失败时用 add()2.移除操作对比
Queue<String>queue=newLinkedList<>();queue.offer("A");// 移除方法对比Stringelem1=queue.remove();// 返回"A",队列空时抛NoSuchElementExceptionStringelem2=queue.poll();// 队列空时返回null// 使用建议:// 1. 需要处理空队列时用 poll()// 2. 确定队列不空时用 remove()3.查看操作对比
Queue<String>queue=newLinkedList<>();queue.offer("A");// 查看方法对比Stringhead1=queue.element();// 返回"A",队列空时抛NoSuchElementExceptionStringhead2=queue.peek();// 队列空时返回null// 使用建议:// 1. 需要处理空队列时用 peek()// 2. 确定队列不空时用 element()3、队列选择
| 队列 | 一句话总结 | 使用建议 |
|---|---|---|
| LinkedList | “什么都能干,但什么都不精” | 需要同时用到队列和列表功能时 |
| ArrayDeque | “单线程下的性能冠军” | 替代 LinkedList,性能要求高时 |
| PriorityQueue | “VIP优先通道” | 需要按优先级处理时 |
| LinkedBlockingQueue | “生产者和消费者的桥梁” | 多线程协作,生产者-消费者模式 |
| ConcurrentLinkedQueue | “高并发下的无锁战士” | 超高并发,读多写多场景 |