目录
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集合中所包含的方法:
java
public interface Collection<E> extends Iterable<E> {
// 基本操作方法
int size();
boolean isEmpty();
boolean contains(Object o);
boolean add(E e);
boolean remove(Object o);
// 批量操作
boolean containsAll(Collection<?> c);
boolean addAll(Collection<? extends E> c);
boolean removeAll(Collection<?> c);
boolean retainAll(Collection<?> c);
void clear();
// 数组转换
Object[] toArray();
<T> T[] toArray(T[] a);
// 迭代器
Iterator<E> iterator();
// Java 8 新增方法
default boolean removeIf(Predicate<? super E> filter) { ... }
default Spliterator<E> spliterator() { ... }
default Stream<E> stream() { ... }
default Stream<E> parallelStream() { ... }
}
1.List集合
List集合的特点就是存取有序,可以存储重复的元素,可以用下标进行元素的操作
该类适用于多线程下读多写少的并发场景,它在有写操作的时候会copy一份数据,然后写完再设置成新的数据,同时也进行了重入锁的处理保证了安全。

1.CopyOnWriteArrayList
CopyOnWriteArrayList 是 Java 并发包中的线程安全 List 实现,采用 "写时复制" 策略

读操作:
java
// 直接读取,无需加锁
public E get(int index) {
return get(getArray(), index); // 直接访问当前数组
}
写操作:
java
// 修改操作(add/set/remove)
public boolean add(E e) {
synchronized (lock) { // 写操作加锁
Object[] elements = getArray();
int len = elements.length;
// 1. 创建新数组(长度+1)
Object[] newElements = Arrays.copyOf(elements, len + 1);
// 2. 在新数组上修改
newElements[len] = e;
// 3. 替换引用
setArray(newElements);
return true;
}
}
2、ArrayList
它是一个标准的集合实现类,特点为有序,可重复,存储是连续的,因此查询较快,增删较为慢,使用Object数组进行存储。
ArrayList 是 Java 中最常用的动态数组实现,基于数组实现,支持动态扩容。
ArrayList底层实现:
java
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
// 默认初始容量
private static final int DEFAULT_CAPACITY = 10;
// 存储元素的数组
transient Object[] elementData; // non-private to simplify nested class access
// 当前元素数量
private int size;
// 空数组实例(用于空列表)
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
}
核心特性
| 特性 | 说明 |
|---|---|
| 数据结构 | 基于数组 |
| 扩容机制 | 增长因子为 1.5 倍 |
| 随机访问 | O(1) 时间复杂度 |
| 插入/删除 | O(n) 时间复杂度(平均) |
| 线程安全 | 非线程安全 |
| 内存连续 | 连续内存分配 |
| 允许元素 | 允许 null 值,允许重复元素 |
构造方法
java
// 1. 默认构造(延迟初始化)
ArrayList<String> list1 = new ArrayList<>(); // 初始容量为0,第一次add时扩容到10
// 2. 指定初始容量
ArrayList<String> list2 = new ArrayList<>(100); // 初始容量100
// 3. 从其他集合构造
List<String> existingList = Arrays.asList("A", "B", "C");
ArrayList<String> list3 = new ArrayList<>(existingList);
扩容过程
java
// add() 方法中的扩容逻辑
public boolean add(E e) {
ensureCapacityInternal(size + 1); // 确保容量足够
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
// 如果是空数组,使用默认容量10
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++; // 修改计数++
// 需要扩容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
// 核心扩容方法
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1); // 增长1.5倍
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 创建新数组并拷贝数据
elementData = Arrays.copyOf(elementData, newCapacity);
}
常用方法详解
1. 添加元素
java
ArrayList<String> list = new ArrayList<>();
// 末尾添加
list.add("A"); // ["A"]
list.add("B"); // ["A", "B"]
// 指定位置插入
list.add(1, "C"); // ["A", "C", "B"] O(n)操作
// 批量添加
list.addAll(Arrays.asList("D", "E")); // ["A", "C", "B", "D", "E"]
// 指定位置批量添加
list.addAll(2, Arrays.asList("X", "Y")); // ["A", "C", "X", "Y", "B", "D", "E"]
2. 访问元素
java
ArrayList<String> list = new ArrayList<>(Arrays.asList("A", "B", "C", "D"));
// 获取元素(随机访问 O(1))
String first = list.get(0); // "A"
String last = list.get(list.size() - 1); // "D"
// 遍历元素
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
// 增强for循环
for (String item : list) {
System.out.println(item);
}
// Java 8+ forEach
list.forEach(System.out::println);
// 迭代器遍历
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
3. 修改元素
java
ArrayList<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
// 设置元素(替换)
list.set(1, "BB"); // ["A", "BB", "C"]
// 批量替换(Java 8+)
list.replaceAll(s -> s + "!"); // ["A!", "BB!", "C!"]
// 排序
list.sort(String::compareTo); // 自然排序
list.sort(Comparator.reverseOrder()); // 逆序
Collections.sort(list); // 传统方式
// 洗牌(随机打乱)
Collections.shuffle(list);
4. 删除元素
java
ArrayList<String> list = new ArrayList<>(
Arrays.asList("A", "B", "C", "D", "E", "B")
);
// 按索引删除(返回被删除元素)
String removed = list.remove(2); // 删除 "C",返回 "C"
// 按元素删除(删除第一个匹配项)
boolean success = list.remove("B"); // 删除第一个 "B",返回 true
list.remove("X"); // 元素不存在,返回 false
// 批量删除
list.removeAll(Arrays.asList("D", "E")); // 删除所有匹配项
// 条件删除(Java 8+)
list.removeIf(s -> s.startsWith("A")); // 删除所有以A开头的元素
// 保留指定元素(交集)
list.retainAll(Arrays.asList("B", "C")); // 只保留 B 和 C
// 清空
list.clear(); // 清空所有元素
5. 查找元素
java
ArrayList<String> list = new ArrayList<>(
Arrays.asList("A", "B", "C", "B", "D")
);
// 查找索引
int firstIndex = list.indexOf("B"); // 1
int lastIndex = list.lastIndexOf("B"); // 3
int notFound = list.indexOf("X"); // -1
// 判断包含
boolean containsB = list.contains("B"); // true
boolean containsAll = list.containsAll(Arrays.asList("A", "C")); // true
// 查找条件匹配(Java 8+)
Optional<String> firstMatch = list.stream()
.filter(s -> s.length() > 1)
.findFirst();
boolean anyMatch = list.stream().anyMatch(s -> s.equals("B"));
boolean allMatch = list.stream().allMatch(s -> s != null);
3、LinkedList
LinkedList 是 Java 中基于双向链表实现的 List,同时也实现了 Deque 接口,可以作为队列或栈使用。
与其他的实现类不同,他的底层是采用链接形式存储的,因此增删块,查询较慢如:
节点结构
java
private static class Node<E> {
E item; // 存储的元素
Node<E> next; // 后继节点
Node<E> prev; // 前驱节点
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
链表结构
java
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable {
transient int size = 0; // 链表大小
transient Node<E> first; // 头节点
transient Node<E> last; // 尾节点
// 节点关系示意图:
// first ←→ node1 ←→ node2 ←→ ... ←→ last
// ↑ ↑ ↑ ↑
// prev=null prev=first prev=node1 prev=...
// next=node1 next=node2 next=node3 next=null
}
核心特性
| 特性 | 说明 |
|---|---|
| 数据结构 | 双向链表 |
| 内存分配 | 非连续内存 |
| 随机访问 | O(n) 时间复杂度 |
| 插入/删除 | O(1) 时间复杂度(已知节点位置) |
| 头尾操作 | O(1) 时间复杂度 |
| 线程安全 | 非线程安全 |
| 允许元素 | 允许 null 值,允许重复元素 |
| 额外空间 | 每个元素需要存储前后指针 |
构造方法
java
// 1. 默认构造(空链表)
LinkedList<String> list1 = new LinkedList<>();
// 2. 从其他集合构造
List<String> existingList = Arrays.asList("A", "B", "C");
LinkedList<String> list2 = new LinkedList<>(existingList);
// 创建后结构:
// first → Node("A") ↔ Node("B") ↔ Node("C") ← last
// size = 3
1. 添加元素
java
LinkedList<String> list = new LinkedList<>();
// 添加到末尾(List接口)
list.add("A"); // [A]
list.add("B"); // [A, B]
// 指定位置插入
list.add(1, "C"); // [A, C, B]
// 添加到末尾(等价于add)
list.addLast("D"); // [A, C, B, D]
// 添加到开头
list.addFirst("Z"); // [Z, A, C, B, D]
// 批量添加
list.addAll(Arrays.asList("E", "F")); // [Z, A, C, B, D, E, F]
2. 访问元素
java
LinkedList<String> list = new LinkedList<>(
Arrays.asList("A", "B", "C", "D", "E")
);
// 获取头尾元素
String first = list.getFirst(); // "A"
String last = list.getLast(); // "E"
// 按索引获取(需要遍历)
String third = list.get(2); // "C" - 从头开始遍历
// 遍历方式
for (int i = 0; i < list.size(); i++) { // ❌ 低效:每次get都是O(n)
System.out.println(list.get(i));
}
// ✅ 推荐:迭代器遍历
for (String item : list) { // 使用迭代器,O(n)总体
System.out.println(item);
}
// ✅ 推荐:列表迭代器(可双向遍历)
ListIterator<String> iterator = list.listIterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
// 反向遍历
while (iterator.hasPrevious()) {
System.out.println(iterator.previous());
}
3. 查找元素
java
LinkedList<String> list = new LinkedList<>(
Arrays.asList("A", "B", "C", "B", "D")
);
// 查找索引(从头开始遍历)
int firstIndex = list.indexOf("B"); // 1
int lastIndex = list.lastIndexOf("B"); // 3
// 判断包含
boolean hasA = list.contains("A"); // true
// 查找条件匹配(Java 8+)
Optional<String> result = list.stream()
.filter(s -> s.startsWith("C"))
.findFirst();
4. 删除元素
java
LinkedList<String> list = new LinkedList<>(
Arrays.asList("A", "B", "C", "D", "E")
);
// 删除头节点
String removedFirst = list.removeFirst(); // "A"
String polledFirst = list.pollFirst(); // "B"(队列风格)
// 删除尾节点
String removedLast = list.removeLast(); // "E"
String polledLast = list.pollLast(); // "D"
// 按索引删除(需要遍历到该位置)
String removed = list.remove(0); // "C"
// 按元素删除(删除第一个匹配项)
boolean success = list.remove("B"); // false("B"已不存在)
// 清空
list.clear(); // first = last = null, size = 0
4、Vector
该类于JDK1.1就出现了,特点为:线程安全但是效率较慢因为他的方法大多采用synchronized进行修饰,也是采用Object数组进行存储
底层数据结构
java
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
// 存储元素的数组
protected Object[] elementData;
// 元素数量
protected int elementCount;
// 容量增长系数(扩容时使用)
protected int capacityIncrement;
// 默认初始容量
private static final int DEFAULT_CAPACITY = 10;
}
核心特性
| 特性 | Vector | ArrayList | 说明 |
|---|---|---|---|
| 线程安全 | ✅ 是(synchronized) | ❌ 否 | Vector 的主要特点 |
| 数据结构 | 动态数组 | 动态数组 | 底层都是数组 |
| 扩容机制 | 可指定增长量,默认2倍 | 固定1.5倍 | Vector 更灵活 |
| 性能 | 较慢(锁开销) | 较快 | Vector 有同步开销 |
| 迭代器 | 快速失败 | 快速失败 | 都支持 fail-fast |
| 遗留类 | ✅ 是(JDK 1.0) | ❌ 否(JDK 1.2) | Vector 已过时 |
构造方法
java
// 1. 默认构造(容量10,满时容量翻倍)
Vector<String> vec1 = new Vector<>();
// 2. 指定初始容量
Vector<String> vec2 = new Vector<>(100);
// 3. 指定初始容量和容量增长量
Vector<String> vec3 = new Vector<>(100, 20);
// 初始容量100,每次扩容增加20
// 4. 从集合构造
List<String> list = Arrays.asList("A", "B", "C");
Vector<String> vec4 = new Vector<>(list);
扩容逻辑
java
// Vector 的扩容方法
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
// 关键:如果有 capacityIncrement,按增量增长;否则翻倍
int newCapacity = oldCapacity +
((capacityIncrement > 0) ? capacityIncrement : oldCapacity);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
扩容示例
java
// 示例1:默认扩容(翻倍)
Vector<Integer> vec1 = new Vector<>(5);
// 初始容量:5
vec1.add(1); vec1.add(2); vec1.add(3); vec1.add(4); vec1.add(5);
vec1.add(6); // 触发扩容:5 → 10(翻倍)
// 示例2:指定增量扩容
Vector<Integer> vec2 = new Vector<>(5, 3);
// 初始容量:5,增量:3
vec2.add(1); vec2.add(2); vec2.add(3); vec2.add(4); vec2.add(5);
vec2.add(6); // 触发扩容:5 → 8(5+3)
vec2.add(7); vec2.add(8);
vec2.add(9); // 触发扩容:8 → 11(8+3)
同步机制
java
// Vector 的所有公共方法都加了 synchronized
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
public synchronized E get(int index) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
return elementData(index);
}
public synchronized E remove(int index) {
modCount++;
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
E oldValue = elementData(index);
int numMoved = elementCount - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index, numMoved);
elementData[--elementCount] = null; // 帮助GC
return oldValue;
}
复合操作的线程安全问题
java
// 即使单个方法是线程安全的,复合操作也可能有问题
Vector<String> vector = new Vector<>();
// ❌ 线程不安全:check-then-act 模式
if (!vector.isEmpty()) { // 线程A检查
String item = vector.get(0); // 线程B可能在这里remove(0)
// 可能抛出 IndexOutOfBoundsException
}
// ✅ 解决方案:对整个复合操作加锁
synchronized(vector) {
if (!vector.isEmpty()) {
String item = vector.get(0);
// 安全操作
}
}
// ❌ 另一个问题:迭代中的修改
for (int i = 0; i < vector.size(); i++) {
String item = vector.get(i); // size()和get()之间可能有其他线程修改
process(item);
}
// ✅ 解决方案:迭代时加锁
synchronized(vector) {
for (int i = 0; i < vector.size(); i++) {
String item = vector.get(i);
process(item);
}
}
1. 容量管理方法
java
Vector<String> vec = new Vector<>(10);
// 获取/设置容量
int capacity = vec.capacity(); // 当前容量:10
vec.ensureCapacity(100); // 确保容量至少100
vec.trimToSize(); // 修剪容量到当前大小
// 设置大小(可能截断或填充null)
vec.setSize(15); // 如果原来小于15,填充null
vec.setSize(5); // 如果原来大于5,截断后面元素
// 获取底层数组
Object[] array = vec.toArray();
2. 元素操作特有方法
java
Vector<String> vec = new Vector<>(Arrays.asList("A", "B", "C", "D"));
// 添加元素(尾部)
vec.addElement("E"); // 同add()
vec.insertElementAt("X", 2); // 在索引2处插入
// 设置元素
vec.setElementAt("BB", 1); // 设置索引1为"BB"
// 删除元素
vec.removeElement("B"); // 删除第一个"B"
vec.removeElementAt(0); // 删除索引0元素
vec.removeAllElements(); // 清空所有元素
// 查找元素
int index = vec.indexOf("C"); // 查找索引
int lastIndex = vec.lastIndexOf("D"); // 从后往前查找
boolean contains = vec.contains("A"); // 是否包含
// 获取首尾元素
String first = vec.firstElement(); // 第一个元素
String last = vec.lastElement(); // 最后一个元素
3. 枚举器(Enumeration)
java
Vector<String> vec = new Vector<>(Arrays.asList("A", "B", "C"));
// 获取枚举器(旧版迭代器)
Enumeration<String> enumeration = vec.elements();
// 遍历
while (enumeration.hasMoreElements()) {
String element = enumeration.nextElement();
System.out.println(element);
}
// 与Iterator对比
Iterator<String> iterator = vec.iterator();
while (iterator.hasNext()) {
String element = iterator.next();
System.out.println(element);
iterator.remove(); // Enumeration没有remove方法
}