前言
Java中的单列集合分为有序的List系列集合和无序的Set系列集合, 对于List集合普通的for循环即可遍历, 但是Set集合无法使用这种方法, 因此Java提供了一种工具类 — Java迭代器, 用于普遍遍历这两种有序和无序的集合
一、Java迭代器
Java迭代器是一种设计模式,用于遍历集合中的元素,而不需要知道集合的内部结构。迭代器提供了一个统一的接口,让用户可以用相同的方式处理不同类型的集合,例如数组、链表、树等。
迭代器模式涉及到三个角色:迭代器接口、具体迭代器和聚合对象。迭代器接口定义了访问和遍历元素的方法,例如hasNext()和next()。具体迭代器实现了迭代器接口,并维护了一个指向当前元素的游标。聚合对象是指包含多个元素的集合,它提供了一个创建迭代器的方法,例如iterator()。
二、迭代器使用方法
在Java中,迭代器接口是java.util.Iterator,它是一个泛型接口,可以适用于任何类型的集合。具体迭代器则由不同的集合类提供,例如java.util.ArrayList、java.util.LinkedList、java.util.TreeSet等。聚合对象则是实现了java.lang.Iterable接口的类,它只有一个方法iterator(),用于返回一个迭代器。
下面是一个简单的例子,演示了如何使用迭代器遍历一个ArrayList:
import java.util.ArrayList;
import java.util.Iterator;
public class IteratorDemo {
public static void main(String[] args) {
// 创建一个ArrayList对象
ArrayList<String> list = new ArrayList<>();
// 添加元素
list.add("Java");
list.add("Python");
list.add("C++");
// 获取一个迭代器对象
Iterator<String> it = list.iterator();
// 使用while循环遍历元素
while (it.hasNext()) {
// 获取当前元素并打印
String element = it.next();
System.out.println(element);
}
}
}
输出结果:
Java
Python
C++
从上面的例子可以看出,使用迭代器遍历集合的步骤如下:
- 通过调用聚合对象的iterator()方法,获取一个迭代器对象。
- 通过调用迭代器对象的hasNext()方法,判断是否还有下一个元素。
- 通过调用迭代器对象的next()方法,获取下一个元素并进行处理。
- 重复步骤2和3,直到遍历完所有元素。
三、迭代器遍历集合的优缺点
1, 迭代器遍历的优点
- 简化了集合的访问方式,无需知道集合的内部结构。
- 提高了代码的复用性和扩展性,可以用同一套代码处理不同类型的集合。
- 隐藏了集合的实现细节,降低了耦合度和依赖性。
- 支持多种遍历方式,例如正向、反向、跳跃等。
2, 迭代器遍历的缺点
- 增加了系统的复杂度,需要额外创建和维护迭代器对象。
- 降低了访问效率,每次访问元素都需要调用两个方法 — hasNext()和next() 。
- 增加了出错的可能性,如果在遍历过程中修改了集合,可能会导致异常或错误。
四、Java迭代器遍历时不能使用集合方法增删的原因
1、在Java中,迭代器是一种用于遍历集合元素的接口,它提供了hasNext(), next(), remove()等方法。但是,如果我们在使用迭代器遍历集合的同时,调用了集合的add(), remove(), clear()等方法,会发生什么呢?
- 答案是会抛出ConcurrentModificationException异常。这个异常表示在迭代过程中,集合的结构被修改了,导致迭代器不再有效。
2、为什么会这样呢?我们来看看迭代器的内部实现。
- 迭代器内部有一个expectedModCount变量,它记录了在创建迭代器时,集合的修改次数(modCount)。每当集合的结构发生变化(增删元素),modCount就会增加。而迭代器在每次调用next()或remove()方法时,都会检查expectedModCount和modCount是否相等,如果不相等,就说明集合被并发修改了,就会抛出异常。
3、为什么迭代器不能容忍集合的并发修改呢?
- 这是因为如果允许这样做,会导致一些不可预期的结果。比如,如果我们在遍历集合的同时删除了一个元素,那么可能会导致某个元素被重复遍历或者遗漏。这样就破坏了迭代器的一致性和正确性。
4、如果我们确实需要在遍历集合的同时修改它,应该怎么做呢?
有两种方法:
- 一种是使用迭代器自己的remove()方法,而不是集合的remove()方法。这样可以保证迭代器和集合的同步,并且不会抛出异常。但是,这种方法只能用于删除元素,不能用于添加元素。
- 另一种是使用一种特殊的迭代器,叫做ListIterator。这种迭代器除了可以删除元素外,还可以添加和修改元素。但是,这种迭代器只能用于List类型的集合,并且需要从指定位置开始遍历。
总结
Java迭代器是一种常用且有效的设计模式,它可以帮助我们简化和统一单列集合(包括List系列和Set系列)的遍历,而Java迭代器遍历时不能使用集合方法增删的原因是为了保证迭代器的一致性和正确性。如果需要在遍历过程中修改集合,可以使用迭代器自己的方法或者ListIterator。