1. 引言
Iterator<E>
是 Java 集合框架中的一个核心接口,它提供了遍历集合的方法。通过调用 List
、Set
等集合的 iterator()
方法,我们可以获取迭代器实例并逐个访问元素。迭代器包含三个核心方法:
-
hasNext()
-
next()
-
remove()
本教程将深入探讨如何创建自定义迭代器并在代码中应用它们。
2. 为什么需要自定义迭代器
在动手实现之前,先明确自定义迭代器的价值。几乎所有集合(如 List
和 Set
)都提供了默认迭代器,我们日常使用它们进行线性遍历:
@Test
public void givenListOfStrings_whenIteratedWithDefaultIterator() {
List<String> listOfStrings = List.of("hello", "world", "this", "is", "a", "test");
Iterator<String> iterator = listOfStrings.iterator();
Assert.assertTrue(iterator.hasNext());
Assert.assertEquals(iterator.next(), "hello");
}
默认迭代器只能实现从左到右的线性遍历,无法满足特殊需求。自定义迭代器通常用于:
✅ 按自定义顺序遍历集合
✅ 遍历时对元素执行额外操作
3. 实现自定义迭代器
本节将通过实际案例展示自定义迭代器的实现。我们将使用以下 Movie
类作为示例:
public class Movie {
private String name;
private String director;
private float rating;
// 标准getter和setter
}
3.1. 为内置数据类型创建自定义迭代器
假设有一个 List<String>
,默认的 iterator()
只能从左到右遍历。现在我们只想遍历其中的回文字符串(正读反读相同的字符串)。这时就需要自定义迭代器。
我们创建 PalindromeIterator
类:
public class PalindromIterator implements Iterator<String> {
@Override
public boolean hasNext() {
// 自定义逻辑
}
@Override
public String next() {
// 自定义逻辑
}
}
首先实现回文检测方法:
private boolean isPalindrome(String input) {
for (int i = 0; i < input.length() / 2; i++) {
if (input.charAt(i) != input.charAt(input.length() - i - 1)) {
return false;
}
}
return true;
}
迭代器需要两个关键属性:
currentIndex
:跟踪当前位置list
:存储集合数据
hasNext()
的实现逻辑是检查是否存在下一个回文字符串:
@Override
public boolean hasNext() {
while (currentIndex < list.size()) {
String currString = list.get(currentIndex);
if (isPalindrome(currString)) {
return true;
}
currentIndex++;
}
return false;
}
next()
方法负责实际遍历,但必须先检查元素存在性,否则会抛出异常:
@Override
public String next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return list.get(currentIndex++);
}
测试用例验证功能:
@Test
public void givenListOfStrings_whenPalindromIterator_thenOnlyPalindromes() {
List<String> listOfStrings = List.of("oslo", "madam", "car", "deed", "wow", "test");
PalindromIterator palindromIterator = new PalindromIterator(listOfStrings);
int count = 0;
while(palindromIterator.hasNext()) {
palindromIterator.next();
count++;
}
assertEquals(count, 3);
}
3.2. 为自定义对象创建迭代器
现在为 List<Movie>
创建迭代器,只遍历评分≥8的电影:
private boolean isMovieEligible(Movie movie) {
return movie.getRating() >= 8;
}
完整迭代器实现:
public class CustomMovieIterator implements Iterator<Movie> {
private int currentIndex;
private final List<Movie> list;
public CustomMovieIterator(List<Movie> list) {
this.list = list;
this.currentIndex = 0;
}
@Override
public boolean hasNext() {
while (currentIndex < list.size()) {
Movie currentMovie = list.get(currentIndex);
if (isMovieEligible(currentMovie)) {
return true;
}
currentIndex++;
}
return false;
}
@Override
public Movie next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return list.get(currentIndex++);
}
}
测试用例:
@Test
public void givenMovieList_whenMovieIteratorUsed_thenOnlyHighRatedMovies() {
List<Movie> movies = getMovies();
CustomMovieIterator movieIterator = new CustomMovieIterator(movies);
int count = 0;
while (movieIterator.hasNext()) {
movieIterator.next();
count++;
}
assertEquals(4, movies.size());
assertEquals(2, count);
}
3.3. 为自定义集合创建迭代器
Java 允许创建自定义集合类。例如实现 List<E>
接口:
public class MyList<E> implements List<E> {
@Override
public int size() {
// 自定义实现
}
@Override
public boolean isEmpty() {
// 自定义实现
}
@Override
public boolean contains(Object o) {
// 自定义实现
}
@Override
public boolean add(E e) {
// 自定义实现
}
@Override
public boolean remove(Object o) {
// 自定义实现
}
}
关键点:必须重写 iterator()
方法返回自定义迭代器:
@Override
public Iterator<E> iterator() {
return new MyListIterator();
}
private class MyListIterator implements Iterator<E> {
@Override
public boolean hasNext() {
// 自定义实现
}
@Override
public E next() {
// 自定义实现
}
}
⚠️ 注意:为简洁省略了方法实现细节。实际开发中,除了 hasNext()
和 next()
,还可以重写 remove()
和 forEachRemaining()
方法。
4. 总结
本文系统介绍了 Java 中自定义迭代器的实现方式,包括:
✅ 为内置数据类型创建迭代器
✅ 为自定义对象创建迭代器
✅ 为自定义集合创建迭代器
自定义迭代器让我们能精确控制集合遍历逻辑。虽然示例基于 List
,但所有实现了 Iterable
接口的集合都可以应用相同模式。掌握这个技巧后,处理复杂遍历需求将变得简单粗暴。