234. Java 集合 - 实现 Iterable 接口(打造你自己的可迭代对象)

14 阅读2分钟

234. Java 集合 - 实现 Iterable 接口(打造你自己的可迭代对象)

在前面学习了 Collection 框架的 Iterator 后,我们可以自己动手实现 Iterable 接口,打造自定义可遍历对象

今天,我们以一个**整数区间(Range)**为例,讲解如何实现一个可以用在 for-each 循环中的类。


🎯 场景需求

创建一个 Range 类,表示一个整数区间,例如从 05。 并且让它支持在 for-each 循环中直接遍历出每一个整数!


🧩 使用 Java 16 的 record(更简洁的写法)

record 是 Java 16 引入的特性,适合用于创建不可变的数据对象。

下面是基于 record 的实现:

import java.util.Iterator;
import java.util.NoSuchElementException;

public record Range(int start, int end) implements Iterable<Integer> {

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

            @Override
            public boolean hasNext() {
                return index < end;
            }

            @Override
            public Integer next() {
                if (index >= end) {
                    throw new NoSuchElementException("No more elements: " + index);
                }
                return index++;
            }
        };
    }
}

讲解重点

  • Range 自动生成了 startend 两个字段。
  • 实现了 Iterable<Integer>,可以直接在 for-each 中使用。
  • 匿名内部类实现了 Iterator<Integer>,内部用一个 index 变量来逐步返回每一个整数。

🏗️ 如果你使用的是早期版本(Java 16 之前)

使用普通的 class 也可以做到同样的效果:

import java.util.Iterator;
import java.util.NoSuchElementException;

public class Range implements Iterable<Integer> {

    private final int start;
    private final int end;

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

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

            @Override
            public boolean hasNext() {
                return index < end;
            }

            @Override
            public Integer next() {
                if (index >= end) {
                    throw new NoSuchElementException("No more elements: " + index);
                }
                return index++;
            }
        };
    }
}

✅ 注意:和 record 版的区别只是结构不同,内部逻辑完全一样!


🔥 使用 Range:自然地在 for-each 中遍历

既然实现了 Iterable<Integer>,我们就可以这样使用 Range

public class TestRange {
    public static void main(String[] args) {
        for (int i : new Range(0, 5)) {
            System.out.println("i = " + i);
        }
    }
}

🖨️ 输出结果

i = 0
i = 1
i = 2
i = 3
i = 4

🚨 小细节提醒

  • Iterator.next() 方法如果没有更多元素,一定要抛出 NoSuchElementException,这是 Java 集合遍历的标准行为。
  • 注意边界处理,hasNext() 的判断条件是 index < end,而不是 index <= end,否则可能超出范围。
  • Iterable 只有一个方法:Iterator<T> iterator(),只要返回了合适的 Iterator,就可以自然支持 for-each 语法!