Iterator 和 Iterable 都是 Java 中表示迭代的接口,本文将基于JDK 17源码,对这两个接口的异同进行分析。
Iterator 和 Iterable 都是 Java 的接口,用于对对象进行迭代,它们的区别主要如下:
- Iterable 意思是可迭代。如果对象实现了 Iterable ,那么可以使用增强的 for 方法(即 for-each 迭代方法
for(int x : list))。它属于java.lang包,相当于语法糖。 - Iterator 意思是迭代器。属于
java.util包。如果类实现了 Iterator,即可创建 Iterator 对象用于遍历。
Iterator
Iterator 接口表示迭代器,它取代了Java中的 Enumeration 接口。和 Enumeration 接口相比,Iterator 接口的方法名更短,并且允许在迭代过程中删除元素(增加了 remove() 方法)。
Enumeration 接口 可以通过 Enumeration.asIterator()转化为 Iterator 接口。
Java 17 中 Iterator 接口的定义为:
public interface Iterator<E> {
boolean hasNext(); // 是否还有元素未访问
E next(); // 返回下一个元素
default void remove() { // 删除最后访问的元素,每次调用 next() 后最多只能调用一次 remove()
throw new UnsupportedOperationException("remove");
}
default void forEachRemaining(Consumer<? super E> action) { // 对每个剩余元素进行操作
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
可以看出 Iterator 的接口比较简单。它主要有两个属性:
hasNext()用于表示是否还有剩余元素next()返回下一个元素
一个方法 remove() 用于删除最后访问的元素。
Java 8 之后增加了 forEachRemaining() 方法,用于对剩余每个元素进行操作。
下面是常用的对象只读访问的遍历示例(这里对 ArrayList 进行遍历):
Iterator<Integer> it = list.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
Iterable
Iterable 表示可迭代。实现 Iterable 接口的对象,可以使用增强的for语句(即 for-each 循环语句)。
Java 17 中 Iterable 接口的定义为:
public interface Iterable<T> {
Iterator<T> iterator(); // 返回Iterator 对象
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
可以看出,Iterable 接口也很简单,有三个方法。
- 方法
iterator(),返回 Iterator 对象,实际上通过 Iterator 接口的方法进行遍历。因此实现了 Iterator 接口的对象,就可以使用 for-each 语法,编译器会转换为调用 Iterable 和 Iterator 接口的方法。 - 方法
forEach()是 Java 8 之后增加的,使用 lambda 对元素遍历的时候进行操作
因此,在使用增强的 for 循环时,
实际上使用的还是 Iterator
总结
Iterable 是一个 Java 语法糖,对象实现这个接口就可以使用 增强型for语句进行遍历。它的底层实现是 Iterator。
Iterator 接口,对象实现这个接口就可以创建 Iterator 对象进行迭代。