Iterable 接口表示一个可迭代的对象集合,其核心含义是 “支持迭代操作”。这意味着,任何实现了 Iterable 接口的类,都具备被遍历的能力,能够通过迭代器(Iterator)依次访问其包含的元素,这也是集合类支持 for-each 循环的基础。
迭代 Iterable 元素的第一种方法是使用 for-each 循环。下面示例展示了如何通过 for-each 循环遍历 List 的元素。由于 List 接口扩展了 Collection 接口,而 Collection 接口扩展了 Iterable 接口,因此 List 对象可以与 for-each 循环一起使用。

示例代码:
import java.util.*;
public class Demo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("one");
list.add("two");
list.add("three");
for( String element : list ){
System.out.println( element.toString() );
}
}
}运行结果:
one two three
此示例首先创建一个新的列表并向其中添加 3 个元素。然后,它使用增强 for 循环来迭代列表的元素,并打印出每个元素的 toString() 值。
遍历 Iterable 元素的第二种方法是通过调用 Iterable 的 iterator() 方法从中获取一个 Iterator。然后,你可以像使用其他迭代器一样遍历该迭代器。例如:
import java.util.*;
public class Demo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("one");
list.add("two");
list.add("three");
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()) {
String element = iterator.next();
System.out.println( element );
}
}
}运行结果:
one two three
遍历 Iterable 元素的第三种方法是使用 forEach() 方法。forEach()方法将 lambda 表达式作为参数。迭代表中的每个元素都会调用一次这个 lambda 表达式。例如:
import java.util.*;
public class Demo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("one");
list.add("two");
list.add("three");
// 迭代
list.forEach( (element) -> {
System.out.println( element );
});
}
}运行结果:
one two three
Iterable 接口有三个方法,其中只有一个需要实现,另外两个方法有默认实现。下面是 Iterable 接口的定义:
package java.lang;
import java.util.Iterator;
import java.util.Objects;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Consumer;
/**
* 实现此接口的对象可以作为增强型for循环(有时称为"for-each循环")的目标。
* 它是Java集合框架中迭代操作的基础接口,提供了统一的元素遍历方式。
*
* <p>任何实现了Iterable接口的类都可以被迭代,这使得客户端代码可以使用一致的方式
* 遍历不同类型的集合,而无需关心其内部实现细节。
*
* @param <T> 迭代器返回的元素类型
*
* @since 1.5 (Java 5引入)
* @jls 14.14.2 增强型for语句规范
*/
public interface Iterable<T> {
/**
* 返回一个用于遍历T类型元素的迭代器。
* 迭代器提供了hasNext()和next()等方法,支持对集合元素的顺序访问。
*
* @return 用于遍历元素的Iterator实例
*/
Iterator<T> iterator();
/**
* 对Iterable中的每个元素执行给定的操作,直到所有元素都被处理或操作抛出异常为止。
* 操作按照迭代顺序执行(如果指定了迭代顺序)。操作抛出的异常会直接传递给调用者。
*
* <p>如果操作执行了修改底层元素源的副作用,此方法的行为是未指定的,
* 除非覆盖此类指定了并发修改策略。
*
* @implSpec (实现规范)
* <p>默认实现的行为等同于:
* <pre>{@code
* for (T t : this)
* action.accept(t);
* }</pre>
*
* @param action 要对每个元素执行的操作
* @throws NullPointerException 如果指定的action为null
* @since 1.8 (Java 8引入,支持函数式编程)
*/
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action); // 确保操作不为null,否则抛出异常
for (T t : this) { // 使用增强for循环遍历所有元素
action.accept(t); // 对每个元素执行消费操作
}
}
/**
* 为当前Iterable描述的元素创建一个Spliterator(可分割迭代器)。
* Spliterator支持并行遍历,是Java 8中为了支持集合并行处理而引入的接口。
*
* @implSpec (实现规范)
* 默认实现从Iterable的迭代器创建一个"早期绑定"的spliterator。
* 该spliterator继承了Iterable迭代器的"快速失败"特性(当检测到并发修改时抛出异常)。
*
* @implNote (实现注意事项)
* 默认实现通常应该被重写。默认实现返回的spliterator具有较差的分割能力,
* 未指定大小,并且不报告任何spliterator特性。实现类几乎总能提供更好的实现。
*
* @return 用于遍历当前Iterable元素的Spliterator
* @since 1.8 (Java 8引入,支持并行流操作)
*/
default Spliterator<T> spliterator() {
// 创建一个未知大小的spliterator,使用当前Iterable的迭代器作为数据源
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}注意,你必须实现的方法名为 iterator()。该方法必须返回一个 Iterator,用于遍历实现 Iterable 接口的对象中的元素。获取迭代器的过程是在幕后进行的,所以你看不到这个过程。当您在 for-each 循环中使用 Iterable 时,Java 编译器会负责生成相关代码。
Iterable 接口是 Java 集合框架的根接口之一,Java 中有多个类实现了 Iterable 接口。因此,这些类可以迭代其内部元素。
还有几个 Java 接口扩展了 Iterable 接口。因此,实现了 Iterable 扩展接口的类也实现了 Iterable 接口。这些类也可以迭代其元素。
Collection 接口扩展了 Iterable,因此 Collection 的所有子类也实现了 Iterable 接口。例如,Java 的 List 和 Set 接口都扩展了 Collection 接口,从而也扩展了 Iterable 接口。如下图:


要实现 Iterable 接口以便使用 for-each 循环,只需完成两个核心步骤:
(1)实现 Iterable 接口并提供 iterator() 方法。
(2)实现对应的 Iterator 接口来定义遍历逻辑。
以下是一个完整示例,展示如何自定义一个可迭代的集合类:
import java.util.Iterator;
// 自定义可迭代的集合类
class MyCollection<T> implements Iterable<T> {
private T[] elements;
private int size;
// 构造方法初始化集合
@SuppressWarnings("unchecked")
public MyCollection(int capacity) {
elements = (T[]) new Object[capacity];
size = 0;
}
// 添加元素方法
public void add(T element) {
if (size < elements.length) {
elements[size++] = element;
}
}
// 实现Iterable接口的核心方法,返回迭代器
@Override
public Iterator<T> iterator() {
return new MyIterator();
}
// 利用内部类实现 Iterator 接口
private class MyIterator implements Iterator<T> {
private int currentIndex = 0; // 跟踪当前迭代位置
// 判断是否还有下一个元素
@Override
public boolean hasNext() {
return currentIndex < size;
}
// 获取下一个元素并移动指针
@Override
public T next() {
return elements[currentIndex++];
}
}
}
public class CustomIterableExample {
public static void main(String[] args) {
// 创建自定义集合并添加元素
MyCollection<String> collection = new MyCollection<>(3);
collection.add("Apple");
collection.add("Banana");
collection.add("Cherry");
// 使用for-each循环遍历(得益于实现了Iterable接口)
for (String fruit : collection) {
System.out.println(fruit);
}
}
}运行结果:
Apple Banana Cherry
注意,迭代器的状态(如 currentIndex)应该封装在 Iterator 实现中,而非 Iterable 类中,这样支持同时创建多个独立的迭代器。如果需要支持移除元素,可以在 Iterator 中重写 remove() 方法,Java 8+ 中还可以选择性重写 forEach() 方法,提供更灵活的遍历方式。
可以通过 spliterator() 方法从 Iterable 获取 Spliterator。例如:
import java.util.ArrayList;
import java.util.List;
import java.util.Spliterator;
public class SpliteratorDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("one");
list.add("two");
list.add("three");
list.add("four");
list.add("five");
// 获取列表的Spliterator
Spliterator<String> spliterator = list.spliterator();
System.out.println("=== 1. 遍历所有元素 ===");
// 使用forEachRemaining遍历元素
spliterator.forEachRemaining(element -> System.out.println(element));
// 重新获取Spliterator
spliterator = list.spliterator();
System.out.println("\n=== 2. 尝试分割Spliterator ===");
// 尝试分割为两个Spliterator
Spliterator<String> secondSpliterator = spliterator.trySplit();
if (secondSpliterator != null) {
System.out.println("--- 第一个部分的元素 ---");
spliterator.forEachRemaining(System.out::println);
System.out.println("--- 第二个部分的元素 ---");
secondSpliterator.forEachRemaining(System.out::println);
}
// 重新获取Spliterator
spliterator = list.spliterator();
System.out.println("\n=== 3. 特性与估计大小 ===");
// 查看Spliterator的特性
int characteristics = spliterator.characteristics();
System.out.println("是否有序: " + ((characteristics & Spliterator.ORDERED) != 0));
System.out.println("是否有大小: " + ((characteristics & Spliterator.SIZED) != 0));
System.out.println("估计元素数量: " + spliterator.estimateSize());
System.out.println("\n=== 4. 逐个处理元素 ===");
// 逐个处理元素
while (spliterator.tryAdvance(element -> System.out.println("处理元素: " + element))) {
// tryAdvance返回true表示还有元素可处理
}
}
}运行结果:
=== 1. 遍历所有元素 === one two three four five === 2. 尝试分割Spliterator === --- 第一个部分的元素 --- three four five --- 第二个部分的元素 --- one two === 3. 特性与估计大小 === 是否有序: true 是否有大小: true 估计元素数量: 5 === 4. 逐个处理元素 === 处理元素: one 处理元素: two 处理元素: three 处理元素: four 处理元素: five
如果你编写的代码需要在一个循环中多次迭代一个集合,比方说每秒迭代一个 List 上千次,那么通过 for-each 进行循环迭代 List 要比通过标准 for 循环迭代 List 慢,示例代码:
import java.util.ArrayList;
import java.util.List;
public class IterablePerformance {
public static void main(String[] args) {
// 初始化一个大小为 1 万的 list
List<String> list = new ArrayList<>();
for(int i = 0; i < 10000; i++) {
list.add(String.valueOf(System.currentTimeMillis()));
}
// 通过传统方式遍历10000次
long s1 = System.currentTimeMillis();
for(int n = 0; n < 10000; n++) {
for(int i = 0; i < list.size(); i++) {
String val = list.get(i);
}
}
System.out.println("传统方式耗时:" + (System.currentTimeMillis() - s1));
// 通过for-each方式遍历10000次
long s2 = System.currentTimeMillis();
for(int n = 0; n < 10000; n++) {
for(String str : list) {
//
}
}
System.out.println("for-each方式耗时:" + (System.currentTimeMillis() - s2));
}
}运行结果:
传统方式耗时:134 for-each方式耗时:262
注意,for-each 循环速度较慢的原因是,每次迭代都会调用 iterator() 方法,从而创建一个新的 Iterator 对象。与使用标准 for 循环迭代 List 相比,每秒创建一个新对象数千次,甚至数百万次,确实会对性能造成一定影响。对于偶尔迭代集合的大多数标准业务应用程序来说,这种性能差异无关紧要。只有在每秒执行数千次的非常紧凑的循环中才会出现这种情况。
更多内容请参考 https://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html API 文档。