1. 引言

Iterator<E> 是 Java 集合框架中的一个核心接口,它提供了遍历集合的方法。通过调用 ListSet 等集合的 iterator() 方法,我们可以获取迭代器实例并逐个访问元素。迭代器包含三个核心方法:

  • hasNext()
  • next()
  • remove()

本教程将深入探讨如何创建自定义迭代器并在代码中应用它们。

2. 为什么需要自定义迭代器

在动手实现之前,先明确自定义迭代器的价值。几乎所有集合(如 ListSet)都提供了默认迭代器,我们日常使用它们进行线性遍历:

@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 接口的集合都可以应用相同模式。掌握这个技巧后,处理复杂遍历需求将变得简单粗暴。


原始标题:Creating Custom Iterator in Java | Baeldung