每日一言
如果什么都不做,那就什么也不会开始。
——《元气少女缘结神》
什么是Iterator
Iterator 迭代器是Java集合Collection框架中的一种机制,是一种用于遍历集合如(列表,集合,映射等实现Collection接口)的类。
原因是 Collection 接口继承了 java.lang.Iterable 接口。Iterable 接口定义了一个核心方法 iterator(),该方法返回一个 Iterator 对象。
因此,任何实现了 Collection 接口的类(如 ArrayList, LinkedList, HashSet, TreeSet 等)都必须提供 iterator() 方法的实现,从而允许你获取一个用于遍历其元素的 Iterator。
使用Iteartor遍历集合
Iterator 类位于java.util包中,使用前需要引入:
import java.util.Ierator;
迭代器接口定义了几个方法:最常用的是以下三个:
- next()-返回迭代器的下一个元素,并将迭代器的指针移到下一个位置
- hashNext()-用于判断集合中是否还有下一个元素可以访问
- remove()-从集合中删除迭代器最后访问的元素
获取Iterator
通过调用Iterator()方法获取Iterator对象:
// 引入 ArrayList 和 Iterator 类
import java.util.ArrayList;
import java.util.Iterator;
public class RunoobTest {
public static void main(String[] args) {
// 创建集合
ArrayList<String> sites = new ArrayList<String>();
sites.add("Google");
sites.add("Runoob");
sites.add("Taobao");
sites.add("Zhihu");
// 获取迭代器
Iterator<String> it = sites.iterator();
System.out.println(it); // 输出迭代器对象
//it.remove(); //抛出异常
// 输出集合中的第一个元素
System.out.println(it.next());
it.remove(); // 删除第一个元素,无返回值
}
}
输出为:
java.util.ArrayList$Itr@4617c264
Google
循环集合元素
让迭代器 it 逐个返回集合中所有元素最简单的方法是使用 while 循环:
while(it.hasNext()) {
System.out.println(it.next());
}
For-each循环
Java 中的 for-each 循环(也称为增强型 for 循环)是一种语法糖(syntactic sugar),它简化了遍历数组或实现了 java.lang.Iterable 接口的集合(如 Collection)的过程。编译器会在编译时将其转换为等效的使用 Iterator 或索引访问的代码。
1. 遍历实现了Collection接口的对象
- 当 for-each 循环用于遍历实现了
Iterable接口的对象时(例如ArrayList,HashSet等),编译器会将其转换为使用Iterator的代码。
原始代码:
List<String> list = new ArrayList<>();
// ... 添加元素 ...
for (String element : list) {
System.out.println(element);
}
编译后的代码:
List<String> list = new ArrayList<>();
// ... 添加元素 ...
Iterator<String> iterator = list.iterator(); // 1. 获取 Iterator
while (iterator.hasNext()) { // 2. 使用 hasNext() 判断
String element = iterator.next(); // 3. 使用 next() 获取元素
System.out.println(element); // 4. 执行循环体
}
我们看一个例子以便加深我们对于Iterator的理解:
// 引入 ArrayList 和 Iterator 类
import java.util.ArrayList;
import java.util.Iterator;
public class RunoobTest {
public static void main(String[] args) {
// 创建集合
ArrayList<String> sites = new ArrayList<String>();
sites.add("Google");
sites.add("Runoob");
sites.add("Taobao");
sites.add("Zhihu");
for(String site : sites) {
if(site.equals("Runoob")) {
site = "Runoob.com";
}
}
for(String site : sites) {
System.out.println(site);
}
}
}
输出:
Google
Runoob
Taobao
Zhihu
我们对于Runoob的修改并没有生效,这里我们解释一下原因:
- Iterator类指向的为集合中元素的地址。
- String类具有不可变性
- Iterator.next()方法返回元素的引用。

由于String的不可变性,没有修改源集合中元素地址中的值,而是将引用指向了另一个地址:

如果我们将String修改为StringBuffer类:
// 引入 ArrayList 和 Iterator 类
import java.util.ArrayList;
import java.util.Iterator; // Iterator 未在此示例中使用,但保留 import
public class RunoobTest {
public static void main(String[] args) {
// 创建集合,使用 StringBuffer
ArrayList<StringBuffer> sites = new ArrayList<StringBuffer>();
sites.add(new StringBuffer("Google"));
sites.add(new StringBuffer("Runoob"));
sites.add(new StringBuffer("Taobao"));
sites.add(new StringBuffer("Zhihu"));
// 遍历并尝试修改 StringBuffer 对象的内容
for(StringBuffer site : sites) {
// 比较 StringBuffer 的内容
if(site.toString().equals("Runoob")) {
// 修改 StringBuffer 对象的内容
site.delete(0, site.length()).append("Runoob.com");
}
}
// 打印修改后的列表内容
for(StringBuffer site : sites) {
System.out.println(site); // 会自动调用 StringBuffer 的 toString()
}
}
}
我们则可以直接修改地址中的内容,从而达到修改集合中元素的效果,运行结果:
Google
Runoob.com
Taobao
Zhihu
2. 遍历数组
当 for-each 循环用于遍历数组时,编译器会将其转换为使用传统索引访问的 for 循环。
原始代码:
String[] array = {"a", "b", "c"};
for (String element : array) {
System.out.println(element);
}
编译后的代码:
String[] array = {"a", "b", "c"};
for (int i = 0; i < array.length; i++) { // 1. 使用索引循环
String element = array[i]; // 2. 通过索引访问元素
System.out.println(element); // 3. 执行循环体
}
遍历数组时哪怕直接使用索引来访问数组,但是在For-each的遍历中,仍然创建一个引用来访问变量。保证了使用for-each循环时的统一性。