234. Java 集合 - 实现 Iterable 接口(打造你自己的可迭代对象)
在前面学习了 Collection 框架的 Iterator 后,我们可以自己动手实现 Iterable 接口,打造自定义可遍历对象!
今天,我们以一个**整数区间(Range)**为例,讲解如何实现一个可以用在 for-each 循环中的类。
🎯 场景需求
创建一个 Range 类,表示一个整数区间,例如从 0 到 5。
并且让它支持在 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自动生成了start和end两个字段。- 实现了
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语法!