【Java源码分析】Iterator 和 Iterable 有什么区别 (JDK 17)

295 阅读2分钟

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 循环时,

image.png 实际上使用的还是 Iterator image.png

总结

Iterable 是一个 Java 语法糖,对象实现这个接口就可以使用 增强型for语句进行遍历。它的底层实现是 Iterator。

Iterator 接口,对象实现这个接口就可以创建 Iterator 对象进行迭代。