Java——集合类
Java 集合类是用于存储和操作数据的核心工具,主要分为Collection和Map两大接口体系,每个接口下有多种实现类。以下是 Java 集合类的完整介绍:
一、集合框架核心接口
1. Collection 接口
集合体系的根接口,定义了添加、删除、遍历等基本操作
三个主要子接口:
- List:有序、可重复元素的集合,支持索引访问
- Set:唯一元素集合,不允许重复值
- Queue:按特定顺序(如 FIFO)处理元素的集合
2. Map 接口
以键值对(Key-Value)形式存储数据,键唯一
二、常用集合类及其特点
1. List 实现类
类名 | 特点 |
---|---|
ArrayList | 基于动态数组实现,随机访问高效,中间位置增删效率低 |
LinkedList | 基于双向链表实现,增删效率高,随机访问效率低 |
Vector | 线程安全,性能低于 ArrayList,已逐渐被淘汰 |
2. Set 实现类
类名 | 特点 |
---|---|
HashSet | 基于哈希表(底层为 HashMap),不保证元素顺序 |
LinkedHashSet | 继承 HashSet,用链表维护插入顺序,插入和访问顺序一致 |
TreeSet | 基于红黑树实现,元素自然排序或按比较器排序 |
3. Queue 实现类
类名 | 特点 |
---|---|
LinkedList | 实现 Deque 接口,可作为双向队列使用 |
PriorityQueue | 基于堆结构,按优先级排序,不允许 null 元素 |
ArrayDeque | 基于数组的双端队列,不允许 null 元素 |
4. Map 实现类
类名 | 特点 |
---|---|
HashMap | 基于哈希表,不保证顺序,允许键值为 null |
LinkedHashMap | 继承 HashMap,用链表维护插入顺序或访问顺序 |
TreeMap | 基于红黑树,按键排序,不允许键为 null |
Hashtable | 线程安全,性能低于 HashMap,不允许键值为 null |
三、线程安全的集合类
- 同步包装类
通过Collections.synchronizedXXX()转换非线程安全集合:
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
- 并发集合类(java.util.concurrent 包)
ConcurrentHashMap:分段锁实现的线程安全 HashMap,性能优于 Hashtable
CopyOnWriteArrayList:写操作时创建副本的线程安全 ArrayList
四、集合常用操作示例
import java.util.*;public class CollectionExample {public static void main(String[] args) {// List操作List<String> list = new ArrayList<>();list.add("apple");list.add("banana");System.out.println(list.get(0)); // 输出: apple// Set操作Set<Integer> set = new HashSet<>();set.add(1);set.add(2);System.out.println(set.contains(1)); // 输出: true// Map操作Map<String, Integer> map = new HashMap<>();map.put("one", 1);map.put("two", 2);System.out.println(map.get("one")); // 输出: 1// 遍历集合for (String element : list) {System.out.println(element);}// Stream API过滤list.stream().filter(e -> e.startsWith("a")).forEach(System.out::println);}
}
五、字典(Map)遍历
1. 遍历键值对(EntrySet)
这是最高效的遍历方式,尤其适合需要同时访问键和值的场景。
Map<String, Integer> map = new HashMap<>();
map.put("apple", 1);
map.put("banana", 2);
map.put("cherry", 3);// 使用for-each循环遍历EntrySet
for (Map.Entry<String, Integer> entry : map.entrySet()) {System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
}// 使用Iterator(适合需要在遍历中删除元素的场景)
Iterator<Map.Entry<String, Integer>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {Map.Entry<String, Integer> entry = iterator.next();if (entry.getValue() == 2) {iterator.remove(); // 安全删除元素}
}
2. 单独遍历键(KeySet)
如果只需要访问键,可以使用这种方式。
// 使用for-each循环遍历键
for (String key : map.keySet()) {System.out.println("Key: " + key);// 如果需要值,可以通过map.get(key)获取,但效率稍低System.out.println("Value: " + map.get(key));
}// 使用Stream API(Java 8+)
map.keySet().stream().forEach(key -> System.out.println("Key: " + key));
3. 单独遍历值(Values)
若只需要访问值,可采用此方式。
// 使用for-each循环遍历值
for (Integer value : map.values()) {System.out.println("Value: " + value);
}
// 使用Stream API收集值到List
List<Integer> valuesList = new ArrayList<>(map.values());
六、集合选择原则
- 有序可重复场景
频繁随机访问:选ArrayList
频繁增删操作:选LinkedList - 唯一元素场景
不要求顺序:选HashSet
需插入顺序:选LinkedHashSet
需排序:选TreeSet - 键值对存储场景
不要求顺序:选HashMap
需排序:选TreeMap - 多线程环境
优先使用ConcurrentHashMap、CopyOnWriteArrayList等并发集合类
七、注意事项
- 迭代修改异常
遍历集合时修改结构会触发ConcurrentModificationException,建议使用Iterator.remove()或for-each循环 - 哈希方法重写
HashMap和HashSet依赖hashCode()和equals(),自定义类需正确重写这两个方法 - 性能优化
ArrayList可指定初始容量减少扩容开销
LinkedList随机访问需遍历链表,避免高频索引操作