1.集合

1.1 Collection和Map集合

1.2List集合和Set集合

- List 家族集合的核心是有序且可重复,Set 家族集合的核心是不可重复,有序性则因具体实现类而异。
- List 家族集合特点
- List 集合是元素有序、可重复的集合,用户可以通过索引(类似数组下标)精确控制元素的插入位 置和访问顺序。
- 有序性:元素的存入顺序和取出顺序完全一致,支持通过索引(get(int index))直接访问指定位置的元素。
- 可重复性:集合中允许存在多个equals()方法返回true的元素,包括多个null值。
- 常用实现类:
- ArrayList:基于动态数组实现,查询效率高,增删效率低(尤其中间位置)。
- LinkedList:基于双向链表实现,增删效率高(尤其首尾),查询效率低。
- Vector:线程安全的动态数组,性能较差,已逐渐被ArrayList替代。
- Set 家族集合特点
- Set 集合的核心是元素不可重复,即不允许存在两个equals()方法返回true的元素,有序性需看具体实现。
- 不可重复性:添加元素时,会通过元素的hashCode()和equals()方法判断是否重复,重复元素会被自动过滤,最多允许一个null值。
- 有序性差异:
- 无序实现类:HashSet,基于哈希表实现,元素存储顺序与存入顺序无关,查找效率高。
- 有序实现类:TreeSet,基于红黑树实现,会按元素的自然顺序(或自定义比较器)对元素进行排序;LinkedHashSet,基于哈希表 + 链表实现,能保证元素的存入顺序与取出顺序一致。
- 常用实现类:HashSet(追求效率)、TreeSet(需要排序)、LinkedHashSet(兼顾顺序与效率)。

2.Collection集合

java
public class CollectionDemo {
public static void main(String[] args) {
// 创建Collection集合(使用ArrayList实现类,因为Collection是接口不能直接实例化)
Collection<String> coll = new ArrayList<>();
// 1. 添加元素:add(E e)、addAll(Collection<? extends E> c)
coll.add("Java");
coll.add("Python");
coll.add("C++");
System.out.println("添加元素后:" + coll); // [Java, Python, C++]
// 创建另一个集合,用于测试addAll
Collection<String> coll2 = new ArrayList<>();
coll2.add("JavaScript");
coll2.add("Go");
coll.addAll(coll2); // 将coll2的所有元素添加到coll中
System.out.println("添加coll2后:" + coll); // [Java, Python, C++, JavaScript, Go]
// 2. 判断元素:contains(Object o)、containsAll(Collection<?> c)、isEmpty()
boolean hasJava = coll.contains("Java");
System.out.println("是否包含Java?" + hasJava); // true
boolean hasAll = coll.containsAll(coll2); // 判断coll是否包含coll2的所有元素
System.out.println("是否包含coll2的所有元素?" + hasAll); // true
boolean isEmpty = coll.isEmpty();
System.out.println("集合是否为空?" + isEmpty); // false
// 3. 获取元素数量:size()
int size = coll.size();
System.out.println("集合元素个数:" + size); // 5
// 4. 删除元素:remove(Object o)、removeAll(Collection<?> c)、clear()
boolean removed = coll.remove("C++"); // 删除指定元素
System.out.println("删除C++是否成功?" + removed); // true
System.out.println("删除后:" + coll); // [Java, Python, JavaScript, Go]
boolean removedAll = coll.removeAll(coll2); // 删除coll中与coll2的交集元素
System.out.println("删除coll2交集元素是否成功?" + removedAll); // true
System.out.println("删除交集后:" + coll); // [Java, Python]
// 5. 遍历元素:iterator()(迭代器遍历)
System.out.print("迭代器遍历元素:");
Iterator<String> it = coll.iterator();
while (it.hasNext()) { // 判断是否有下一个元素
String elem = it.next(); // 获取下一个元素
System.out.print(elem + " ");
}
System.out.println(); // 输出:Java Python
// 6. 转换为数组:toArray()
Object[] array = coll.toArray();
System.out.print("转换为数组后:");
for (Object obj : array) {
System.out.print(obj + " ");
}
System.out.println(); // 输出:Java Python
// 7. 清空集合:clear()
coll.clear();
System.out.println("清空后集合:" + coll); // []
System.out.println("清空后是否为空?" + coll.isEmpty()); // true
}
}
代码说明:
1.方法覆盖:包含了 Collection 接口的所有通用方法
(add、addAll、remove、removeAll、contains、containsAll、size、isEmpty、iterator、toArray、clear)。
2.实现类选择:用 ArrayList 实例化 Collection,因为接口不能直接创建对象,需通过具体实现类
(ArrayList、HashSet 等都可,此处以常用的 ArrayList 为例)。
3.核心逻辑:通过逐步操作展示集合从创建、添加元素、判断元素、删除元素到遍历、清空的完整流程,
直观体现 Collection 方法的作用。
3.迭代器

3.1 迭代器(Iterator)遍历(最基础、通用的方式)
Iterator 是 Collection 接口提供的通用遍历工具,所有实现类都支持,适用于所有 Collection 集合(包括 Set,因为 Set 无索引)。
核心方法:
hasNext():判断是否有下一个元素。
next():获取下一个元素(注意:必须先调用 hasNext() 判断,否则可能抛出 NoSuchElementException)。
remove():删除当前迭代的元素(可选操作,需谨慎使用)。
- 迭代器(Iterator)遍历(最基础、通用的方式)
- Iterator 是 Collection 接口提供的通用遍历工具,所有实现类都支持,适用于所有 Collection 集合(包括 Set,因为 Set 无索引)。
核心方法:- hasNext():判断是否有下一个元素。
- next():获取下一个元素(注意:必须先调用 hasNext() 判断,否则可能抛出 NoSuchElementException)。
- remove():删除当前迭代的元素(可选操作,需谨慎使用)。
java
public class CollectionTraversal {
public static void main(String[] args) {
Collection<String> coll = new ArrayList<>();
coll.add("Java");
coll.add("Python");
coll.add("C++");
// 获取迭代器对象
Iterator<String> it = coll.iterator();
// 遍历
while (it.hasNext()) {
String elem = it.next(); // 获取元素
System.out.println(elem);
}
}
}
3.2 增强 for 循环(foreach,JDK 5+)
- 简化版的迭代器遍历,语法更简洁,适用于只需要 "读取" 元素,不需要 "修改集合结构"(如增删元素)的场景。

java
// 承接上面的elems集合
for (String elem : elems) {
System.out.println(elem);
}
3.3 Lambda表达式

- 注意:增强 for 循环底层也是迭代器,若在循环中使用集合的 remove() 方法修改集合结构,会抛出 ConcurrentModificationException(并发修改异常)。如需删除元素,需用迭代器的 remove() 方法。
3.4 普通 for 循环(仅适用于 List 集合)
- 利用 List 集合的索引(get(int index) 方法)遍历,仅支持 List 及其实现类(如 ArrayList、LinkedList),Set 集合无索引,不能使用。
java
public class ListForLoop {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("C++");
// 普通for循环(依赖索引)
for (int i = 0; i < list.size(); i++) {
String elem = list.get(i);
System.out.println(elem);
}
}
}
3.5 JDK 8+ 流式遍历(forEach + Lambda)
- 基于 Stream API 的遍历方式,语法简洁,支持函数式编程,可结合过滤、映射等操作。
java
// 承接上面的coll集合
coll.forEach(elem -> System.out.println(elem));
// 简化写法(方法引用)
coll.forEach(System.out::println);
4.并发修改异常(ConcurrentModificationException)
- 是一种常见错误,通常发生在 "遍历集合的同时修改集合结构(增删元素)" 的场景中。
java
public class CollectionTraversalTest6 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("Java入门");
list.add("宁夏枸杞");
list.add("黑枸杞");
list.add("人字拖");
list.add("特级枸杞");
list.add("枸杞子");
list.add("西洋参");
// 需求1:删除全部枸杞
for (int i = 0; i < list.size(); i++) {
String name = list.get(i);
if (name.contains("枸杞")) {
list.remove(name);
i--; // 删除后索引回退,保证后续元素不被跳过
}
}
System.out.println(list);
}
}
输出结果:[Java 入门,黑枸杞,人字拖,枸杞子,西洋参]
删除了宁夏枸杞后,跳过了黑枸杞,删除了特技枸杞后跳过了枸杞子,这是怎么回事?
原因是:index索引[1]到了宁夏枸杞这个位置,把宁夏枸杞删除后,黑枸杞自动跑到了索引[2],
而iterator.hasNext()会自动往后走1个索引,故index接下来走到了[2]对应的是人字拖,跳过了黑枸杞.
解决方案↓
通过迭代器方式实现(更符合 "避免并发修改异常" 的规范场景)
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String name = iterator.next();
if (name.contains("枸杞")) {
iterator.remove(); // 用迭代器的remove方法,避免索引问题
}
}
System.out.println(list);
执行修正后的代码,输出为:[Java入门, 人字拖, 西洋参](所有含 "枸杞" 的元素均被删除)。
- 产生原因
Java 集合(如ArrayList、HashMap等)的迭代器(Iterator)采用了快速失败(fail-fast)机制:迭代器在创建时会记录集合的「修改次数」,遍历过程中会实时检查这个次数。如果发现集合被意外修改(如通过集合自身的add()、remove()方法,而非迭代器的remove()),就会立即抛出ConcurrentModificationException,避免迭代过程中出现数据不一致。
4.1单线程中边遍历边修改集合
java
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
// 遍历集合
for (String s : list) { // 增强for循环底层依赖Iterator
if (s.equals("A")) {
list.remove(s); // 直接通过集合修改,触发异常
}
}
- 多线程并发操作集合一个线程在遍历集合,另一个线程同时修改集合,也可能触发该异常。
4.2解决方案
- 使用迭代器自身的remove()方法迭代器的remove()会同步更新「修改次数」,避免异常:
java
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String s = iterator.next();
if (s.equals("A")) {
iterator.remove(); // 正确:通过迭代器修改
}
}
注意:迭代器的remove()只能在next()之后调用,且每次next()后只能调用一次。
- 使用普通 for 循环(基于索引)适用于有序集合(如ArrayList),通过索引遍历并修改:
java
for (int i = 0; i < list.size(); i++) {
if (list.get(i).equals("A")) {
list.remove(i);
i--; // 删除后索引需回退,避免跳过元素
}
}
5.倒着遍历也能解决问题!!
