ZetCode

Java Iterable 接口

最后修改时间:2025 年 4 月 13 日

java.lang.Iterable 接口是 Java 集合框架的一个基本组成部分,它为支持迭代的对象定义了一个约定。它是所有集合类型(包括 ListSetQueue)的父接口。通过实现 Iterable,一个类可以使用增强型 for 循环进行遍历,从而简化迭代逻辑并提高代码可读性。

Iterable 接口在 Java 5 中引入,它提供了一种获取迭代器的方法,该机制允许顺序访问元素,而无需暴露底层表示。后来,在 Java 8 中,它被扩展了默认方法,提供了更大的灵活性和更有效处理集合的其他方法。理解 Iterable 对于使用 Java 集合和设计与现有 API 无缝集成的自定义可迭代结构至关重要。

Iterable 接口方法

Iterable 接口定义了三个关键方法,用于迭代元素。主要方法iterator,而 forEachspliterator 是在 Java 8 中作为默认方法引入的,以增强迭代能力。

public interface Iterable<T> {
    Iterator<T> iterator();
    default void forEach(Consumer<? super T> action) {...}
    default Spliterator<T> spliterator() {...}
}

iterator 方法是任何实现 Iterable 的类的核心要求;它提供了一个 Iterator 实例,该实例有助于对元素进行受控的顺序访问forEach 方法支持函数式迭代,允许使用 lambda 表达式来简化元素处理。同时,spliterator 有助于并行执行,特别有利于高性能计算任务,在这些任务中,高效处理大量数据至关重要。

通过实现 Iterable,开发人员可以使其自定义数据结构无缝集成到 Java 的迭代机制中,从而提高代码的可维护性和性能。理解这些方法及其应用可以更好地在现代 Java 应用程序中进行集合处理、函数式编程并行执行

基本 Iterable 实现

此示例演示如何在自定义类中实现 Iterable 接口。我们创建一个简单的类似集合的类,该类保存元素并提供迭代能力。

Main.java
class SimpleCollection<T> implements Iterable<T> {
    
    private T[] elements;
    private int size;
    
    @SuppressWarnings("unchecked")
    public SimpleCollection(int capacity) {
        elements = (T[]) new Object[capacity];
        size = 0;
    }
    
    public void add(T element) {
        if (size < elements.length) {
            elements[size++] = element;
        }
    }
    
    @Override
    public Iterator<T> iterator() {
        return new Iterator<T>() {
            private int currentIndex = 0;
            
            @Override
            public boolean hasNext() {
                return currentIndex < size;
            }
            
            @Override
            public T next() {
                if (!hasNext()) {
                    throw new NoSuchElementException();
                }
                return elements[currentIndex++];
            }
        };
    }
}

void main() {

    SimpleCollection<String> collection = new SimpleCollection<>(3);
    collection.add("First");
    collection.add("Second");
    collection.add("Third");
    
    for (String item : collection) {
        System.out.println(item);
    }
}

在此示例中,我们创建一个实现 Iterable 的 SimpleCollection 类。该类维护一个元素数组,并提供一个作为匿名内部类的迭代器实现。增强型 for 循环适用于我们的自定义集合,因为它实现了 Iterable。

使用 forEach 方法

Java 8 中添加的 forEach 方法对 Iterable 的每个元素执行给定的操作,直到所有元素都已被处理。此方法简化了使用 lambda 表达式的迭代。

Main.java
void main() {

    List<String> languages = List.of("Java", "Python", "C++", "JavaScript");

    // Traditional for-loop
    System.out.println("Traditional iteration:");
    for (String lang : languages) {
        System.out.println(lang);
    }

    // Using forEach with lambda
    System.out.println("\nUsing forEach:");
    languages.forEach(lang -> System.out.println(lang));

    // Using method reference
    System.out.println("\nUsing method reference:");
    languages.forEach(System.out::println);
}

此示例显示了迭代 List(它实现了 Iterable)的不同方法。 forEach 方法提供了一种使用 lambda 表达式或方法引用处理每个元素的简洁方法,使代码更具可读性和表现力。

自定义迭代器实现

此示例演示如何为专门的数据结构创建更复杂的自定义迭代器。我们将实现一个范围迭代器,该迭代器生成指定范围内的数字。

Main.java
class NumberRange implements Iterable<Integer> {

    private final int start;
    private final int end;
    private final int step;

    public NumberRange(int start, int end, int step) {
        this.start = start;
        this.end = end;
        this.step = step;
    }

    @Override
    public Iterator<Integer> iterator() {
        return new Iterator<>() {
            private int current = start;

            @Override
            public boolean hasNext() {
                return step > 0 ? current <= end : current >= end;
            }

            @Override
            public Integer next() {
                if (!hasNext()) {
                    throw new NoSuchElementException();
                }
                int value = current;
                current += step;
                return value;
            }
        };
    }
}

void main() {
    
    System.out.println("Positive step:");
    for (int num : new NumberRange(1, 10, 2)) {
        System.out.println(num);
    }

    System.out.println("\nNegative step:");
    for (int num : new NumberRange(10, 1, -2)) {
        System.out.println(num);
    }
}

此示例创建一个 NumberRange 类,该类生成从开始到结束,具有给定步长的数字。该迭代器可以正确处理正步长和负步长。该实现显示了如何创建在迭代期间保持其位置的有状态的迭代器。

具有原始类型的 Iterable

虽然 Iterable 适用于对象,但我们可以使用包装类为原始类型创建专门的实现。此示例显示了原始 int 值的 iterable。

Main.java
class IntRange implements Iterable {
    
    private final int[] values;

    public IntRange(int... values) {
        this.values = values;
    }

    @Override
    public Iterator<Integer> iterator() {
        return new Iterator<>() {
            private int index = 0;

            @Override
            public boolean hasNext() {
                return index < values.length;
            }

            @Override
            public Integer next() {
                if (!hasNext()) {
                    throw new NoSuchElementException();
                }
                return values[index++];
            }
        };
    }
}

void main() {

    IntRange range = new IntRange(10, 20, 30, 40, 50);

    // Using enhanced for-loop
    for (int num : range) {
        System.out.println(num);
    }

    // Using forEach
    range.forEach(num -> System.out.println(num * 2));
}

此示例创建一个 IntRange 类,该类保存原始 int 值,但通过 Integer 对象提供迭代。该类演示了如何在仍然实现 Iterable 接口的情况下使用原始值,以便与 Java 的集合框架一起使用。

嵌套 Iterable 实现

此示例演示如何为具有嵌套元素的更复杂的数据结构实现 Iterable。我们将创建一个 Matrix 类,该类允许逐行迭代所有元素。

Main.java
class Matrix<T> implements Iterable<T> {

    private final T[][] data;
    private final int rows;
    private final int cols;

    @SuppressWarnings("unchecked")
    public Matrix(int rows, int cols) {
        this.rows = rows;
        this.cols = cols;
        data = (T[][]) new Object[rows][cols];
    }

    public void set(int row, int col, T value) {

        if (row >= rows || col >= cols || row < 0 || col < 0) {
            throw new IndexOutOfBoundsException("Invalid matrix position");
        }

        data[row][col] = value;
    }

    public T get(int row, int col) {
        return data[row][col];
    }

    @Override
    public Iterator<T> iterator() {
        return new Iterator<>() {
            private int row = 0;
            private int col = 0;

            @Override
            public boolean hasNext() {
                return row < rows;
            }

            @Override
            public T next() {
                if (!hasNext()) {
                    throw new NoSuchElementException();
                }

                T value = data[row][col];

                // Move to next element
                col++;
                if (col >= cols) {
                    col = 0;
                    row++;
                }

                return value;
            }
        };
    }
}


void main() {

    Matrix<String> matrix = new Matrix<>(2, 3);

    matrix.set(0, 0, "A1");
    matrix.set(0, 1, "A2");
    matrix.set(0, 2, "A3");
    matrix.set(1, 0, "B1");
    matrix.set(1, 1, "B2");
    matrix.set(1, 2, "B3");

    System.out.println("Matrix elements:");
    for (String element : matrix) {
        System.out.println(element);
    }
}

这个改进的 Matrix 类将元素存储在一个二维数组中,同时提供了一个通过所有元素的 *平面迭代*。迭代器正确地保持了它在行和列中的位置,展示了一种处理复杂迭代的 *结构化方法*,同时仍然实现了 Iterable 接口。

来源

Java Iterable 接口文档

在本文中,我们通过实际示例介绍了 Java Iterable 接口。理解 Iterable 对于使用 Java 集合和创建与 Java 的增强型 for 循环和流 API 无缝集成的自定义可迭代数据结构至关重要。

作者

我叫 Jan Bodnar,是一位经验丰富的程序员。我于 2007 年开始撰写编程文章,至今已撰写超过 1400 篇文章和八本电子书。凭借超过八年的教学经验,我致力于分享我的知识并帮助其他人掌握编程概念。

列出所有Java教程