【Java】吃透集合框架:List、Set、Queue 和 Map 的核心用法与代码实战
大家好,我是云扬~ 今天来和大家深入聊聊 Java 集合框架中最核心的四大组件:List、Set、Queue 和 Map。作为后端开发中高频使用的数据结构,它们各自有着独特的特性和适用场景,掌握好它们的用法能让我们的代码更高效、更优雅。下面结合具体特征和代码示例,带大家全面吃透这些集合类~
一、集合框架总览
Java 集合框架的核心是Collection接口和Map接口,其中Collection主要包含三大分支:
- List:有序、可重复,支持下标操作
- Set:无序、不可重复,无下标支持
- Queue:遵循特定顺序(如 FIFO)的队列结构
- Map:独立于 Collection,存储键值对(key 唯一,value 可重复)
先上一张核心接口关系图,帮大家建立整体认知:
Collection
├── List(有序可重复)
│ ├── ArrayList(数组实现)
│ ├── LinkedList(链表实现)
│ └── Vector(线程安全,低效)
├── Set(无序不可重复)
│ ├── HashSet(哈希实现,去重)
│ ├── LinkedHashSet(有序去重)
│ └── TreeSet(排序去重)
└── Queue(队列)
├── ArrayDeque(双端队列)
├── LinkedList(队列实现)
└── PriorityQueue(优先级队列)
Map
├── HashMap(哈希实现,无序)
├── LinkedHashMap(有序键值对)
└── TreeMap(排序键值对)
二、List:有序可重复的动态数组
List 的核心优势是存取有序、支持下标操作,适合需要按顺序存储且可能重复的数据场景。
1. ArrayList(数组实现,随机存取高效)
核心特征:基于动态数组,随机访问快(O (1)),中间增删慢(需复制移动元素),非线程安全。
代码示例:ArrayList 的增删改查
import java.util.ArrayList;
import java.util.List;
public class ArrayListDemo {
public static void main(String[] args) {
// 初始化ArrayList(初始容量16,负载因子0.75)
List<String> list = new ArrayList();
// 增:尾部添加(高效)
list.add("Java");
list.add("MySQL");
list.add("Java"); // 允许重复元素
System.out.println("添加后:" + list); // 输出:[Java, MySQL, Java]
// 改:通过下标修改
list.set(1, "Redis");
System.out.println("修改后:" + list); // 输出:[Java, Redis, Java]
// 查:随机访问(高效)
String element = list.get(0);
System.out.println("下标0的元素:" + element); // 输出:Java
// 删:中间删除(低效,需移动元素)
list.remove(2);
System.out.println("删除后:" + list); // 输出:[Java, Redis]
// 遍历(下标遍历最高效)
for (int i = 0; i < list.size(); i++) {
System.out.println("遍历元素:" + list.get(i));
}
}
}
2. LinkedList(双向链表,增删高效)
核心特征:基于双向链表,中间增删快(O (1)),随机访问慢(O (n)),支持队列 / 栈操作。
代码示例:LinkedList 的队列用法
import java.util.LinkedList;
import java.util.Queue;
public class LinkedListDemo {
public static void main(String[] args) {
// 作为队列使用(FIFO)
Queue<String> queue = new LinkedList<>();
// 入队:offer()(推荐,失败返回false)
queue.offer("任务1");
queue.offer("任务2");
queue.offer("任务3");
System.out.println("队列内容:" + queue); // 输出:[任务1, 任务2, 任务3]
// 出队:poll()(移除并返回头部,空队列返回null)
String task = queue.poll();
System.out.println("执行任务:" + task); // 输出:任务1
System.out.println("出队后:" + queue); // 输出:[任务2, 任务3]
// 查看头部:peek()(不删除)
String head = queue.peek();
System.out.println("当前头部任务:" + head); // 输出:任务2
// 作为链表,中间插入(高效)
List<String> linkedList = new LinkedList<>(queue);
linkedList.add(1, "紧急任务");
System.out.println("插入后:" + linkedList); // 输出:[任务2, 紧急任务, 任务3]
}
}
3. 避坑提醒
- 避免用
Vector和Stack:Vector 是线程安全的 ArrayList,但效率极低;Stack 已被 ArrayDeque 取代。 - 大数据量场景:如果需要频繁增删,优先用 LinkedList;需要频繁查询,优先用 ArrayList。
三、Set:无序不可重复的去重神器
Set 的核心价值是自动去重,适合存储不需要重复的数据(如用户 ID、关键词等)。
1. HashSet(基于 HashMap,去重首选)
核心特征:底层是 HashMap(值为固定 Object),无序,去重效率高,允许 null 元素。
代码示例:HashSet 去重实战
import java.util.HashSet;
import java.util.Set;
public class HashSetDemo {
public static void main(String[] args) {
// 统计文章中不重复的单词
String article = "Java 是最好的语言 Java 语言 后端开发 最好的";
String[] words = article.split(" ");
Set<String> uniqueWords = new HashSet<>();
for (String word : words) {
uniqueWords.add(word); // 自动去重
}
System.out.println("不重复单词数:" + uniqueWords.size()); // 输出:5
System.out.println("不重复单词:" + uniqueWords); // 输出:[Java, 语言, 最好的, 后端开发, 是](无序)
}
}
2. LinkedHashSet(有序去重)
核心特征:继承 HashSet,底层是 LinkedHashMap,既保留去重特性,又能维护插入顺序。
import java.util.LinkedHashSet;
import java.util.Set;
public class LinkedHashSetDemo {
public static void main(String[] args) {
Set<String> set = new LinkedHashSet<>();
set.add("张三");
set.add("李四");
set.add("张三"); // 去重
set.add("王五");
// 输出顺序与插入顺序一致
System.out.println(set); // 输出:[张三, 李四, 王五]
}
}
3. TreeSet(排序去重)
核心特征:底层是 TreeMap,按自然顺序或自定义比较器排序,不允许 null 元素。
import java.util.TreeSet;
import java.util.Set;
public class TreeSetDemo {
public static void main(String[] args) {
// 自然排序(整数升序)
Set<Integer> numSet = new TreeSet numSet.add(3);
numSet.add(1);
numSet.add(2);
numSet.add(3); // 去重
System.out.println("自然排序:" + numSet); // 输出:[1, 2, 3]
// 自定义比较器(字符串长度降序)
Set> strSet = new TreeSet s2) -> s2.length() - s1.length());
strSet.add("apple");
strSet.add("banana");
strSet.add("cherry");
System.out.println("自定义排序:" + strSet); // 输出:[banana, cherry, apple]
}
}
四、Queue:遵循规则的队列结构
Queue 的核心是遵循特定访问顺序,常见场景:任务队列、消息队列等。
1. ArrayDeque(双端队列,高效替代 Stack)
核心特征:基于循环数组,支持两端增删(O (1)),随机访问快,效率高于 LinkedList。
import java.util.ArrayDeque;
import java.util.Deque;
public class ArrayDequeDemo {
public static void main(String[] args) {
// 作为栈使用(LIFO)
Deque<String> stack = new ArrayDeque<>();
stack.push("页面A");
stack.push("页面B");
stack.push("页面C");
System.out.println("栈顶元素:" + stack.peek()); // 输出:页面C
String popPage = stack.pop();
System.out.println("出栈元素:" + popPage); // 输出:页面C
System.out.println("栈剩余:" + stack); // 输出:[页面B, 页面A]
// 作为双端队列,两端操作
Deque<String> deque = new ArrayDeque<>();
deque.addFirst("头部元素");
deque.addLast("尾部元素");
System.out.println("双端队列:" + deque); // 输出:[头部元素, 尾部元素]
deque.removeFirst();
deque.removeLast();
System.out.println("清空后:" + deque); // 输出:[]
}
}
2. PriorityQueue(优先级队列)
核心特征:基于堆结构,出队顺序按优先级(默认升序),元素需实现 Comparable 接口。
import java.util.PriorityQueue;
import java.util.Queue;
// 自定义任务类,实现Comparable接口
class Task implements Comparable<Task> {
private String name;
private int priority; // 优先级:数字越大越优先
public Task(String name, int priority) {
this.name = name;
this.priority = priority;
}
@Override
public int compareTo(Task o) {
// 降序排序(优先级高的先出队)
return o.priority - this.priority;
}
@Override
public String toString() {
return name + "(优先级:" + priority + ")";
}
}
public class PriorityQueueDemo {
public static void main(String[] args) {
Queue queue = new PriorityQueue();
queue.offer(new Task("普通任务", 1));
queue.offer(new Task("紧急任务", 3));
queue.offer(new Task("重要任务", 2));
// 按优先级出队
while (!queue.isEmpty()) {
System.out.println("执行任务:" + queue.poll());
}
// 输出顺序:紧急任务(优先级:3) → 重要任务(优先级:2) → 普通任务(优先级:1)
}
}
五、Map:键值对的高效存储
Map 是键值对集合,核心是通过 key 快速查找 value,key 唯一且不可重复。
1. HashMap(哈希实现,日常首选)
核心特征:底层是哈希表(数组 + 链表 / 红黑树),查询效率高(O (1)),无序,key 和 value 均可为 null。
代码示例:HashMap 的常用操作
import java.util.HashMap;
import java.util.Map;
public class HashMapDemo {
public static void main(String[] args) {
Map<String, Integer> userAge = new HashMap<>();
userAge.put("张三", 25);
userAge.put("李四", 30);
userAge.put("王五", 28);
userAge.put("张三", 26); // key重复,覆盖value
System.out.println("HashMap内容:" + userAge); // 输出:{李四=30, 张三=26, 王五=28}(无序)
// 查:get()
int age = userAge.get("李四");
System.out.println("李四的年龄:" + age); // 输出:30
// 判存:containsKey()/containsValue()
boolean hasZhang = userAge.containsKey("张三");
boolean hasAge30 = userAge.containsValue(30);
System.out.println("是否包含张三:" + hasZhang); // 输出:true
System.out.println("是否有30岁用户:" + hasAge30); // 输出:true
// 遍历:forEach()
System.out.println("遍历键值对:");
userAge.forEach((key, value) -> System.out.println(key + ":" + value));
// 删:remove()
userAge.remove("王五");
System.out.println("删除后:" + userAge); // 输出:{李四=30, 张三=26}
}
}
2. LinkedHashMap(有序键值对)
核心特征:继承 HashMap,通过双向链表维护插入 / 访问顺序,适合需要保留顺序的场景(如缓存 LRU)。
import java.util.LinkedHashMap;
import java.util.Map;
public class LinkedHashMapDemo {
public static void main(String[] args) {
// 维护插入顺序
Map<String, String> map = new LinkedHashMap<>();
map.put("a", "苹果");
map.put("b", "香蕉");
map.put("c", "樱桃");
// 输出顺序与插入顺序一致
System.out.println("插入顺序:" + map); // 输出:{a=苹果, b=香蕉, c=樱桃}
// 访问元素后,顺序不变(默认插入顺序)
map.get("b");
System.out.println("访问后顺序:" + map); // 输出:{a=苹果, b=香蕉, c=樱桃}
// 构造函数设置为访问顺序(LRU缓存核心)
Map<String,String> lruMap = new LinkedHashMap<>( 10,0.75f, true);
lruMap.put("a", "苹果");
lruMap.put("b", "香蕉");
lruMap.put("c", "樱桃");
lruMap.get("b"); // 访问b
System.out.println("LRU访问顺序:" + lruMap); // 输出:{a=苹果, c=樱桃, b=香蕉}(最近访问的放最后)
}
}
3. TreeMap(排序键值对)
核心特征:底层是红黑树,按 key 自然排序或自定义排序,适合需要排序的键值对场景。
import java.util.TreeMap;
import java.util.Map;
public class TreeMapDemo {
public static void main(String[] args) {
// 自然排序(字符串字典序)
Map<String, Integer> treeMap = new TreeMap<>();
treeMap.put("banana", 3);
treeMap.put("apple", 1);
treeMap.put("cherry", 2);
System.out.println("自然排序:" + treeMap); // 输出:{apple=1, banana=3, cherry=2}
// 自定义比较器(按key长度排序)
Map<String, Integer> customTreeMap = new TreeMap<>((k1, k2) -> k1.length() - k2.length());
customTreeMap.put("banana", 3);
customTreeMap.put("apple", 1);
customTreeMap.put("pear", 2);
System.out.println("自定义排序:" + customTreeMap); // 输出:{pear=2, apple=1, banana=3}
}
}
六、总结:集合类选择指南
| 场景需求 | 推荐集合 |
|---|---|
| 有序可重复、频繁查询 | ArrayList |
| 有序可重复、频繁增删 | LinkedList |
| 去重、无序 | HashSet |
| 去重、有序 | LinkedHashSet |
| 去重、排序 | TreeSet |
| 队列、栈操作 | ArrayDeque |
| 优先级任务队列 | PriorityQueue |
| 键值对、无序、高效查询 | HashMap |
| 键值对、有序 | LinkedHashMap |
| 键值对、排序 | TreeMap |
以上就是 Java 集合框架核心组件的全部内容啦~ 每个集合类都有其设计初衷,掌握它们的底层实现和适用场景,才能在实际开发中做出最优选择。如果大家有疑问或补充,欢迎在评论区交流~ 下期再见!



