【JDK源码】Iterator与Iterable的实现与区别
JAVA
本/文/前/言
JAVA
1. 在介绍Iterator与Iterable接口之前,需要了解Iterator与Iterable接口在Java类库家族谱中的地位。如下图0-1所示。
一、Iterable接口的地位
如图0-1所示,Iterable接口是List、Set、Collection的最高父类接口。
而iterator为Java中的迭代器对象,是能够对List这样的集合进行迭代遍历的底层依赖。iterable接口里定义了返回iterator的方法,相当于对iterator的封装,同时实现了iterable接口的类可以支持forEach循环。
综上:
1.Iterable接口是各Java类集框架的最高级接口;
2.iterator接口作为Iterable接口中一个方法的返回类型。
二、iterator接口的内部方法
public interface Iterator<E> {
//如果仍有元素可以迭代,则返回 true。
boolean hasNext();
//返回迭代的下一个元素。
E next();
//对迭代器剩下还未迭代的元素遍历,用lamda表达式。
default void forEachRemaining(Consumer<? super E>
action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
Iterator是一个“迭代器”的概念,无论是在JavaScript语言、Java语言或是jQuery框架都是一种底层支撑,Iterator迭代器中的方法类似数据库查询结果对象中的“游标”。
//如果仍有元素可以迭代,则返回 true。
boolean hasNext();
判断“迭代器”对象中,是否有下一个元素可以迭代。
//返回迭代的下一个元素。
E next();
返回“迭代器”对象中的下一个元素。
//对迭代器剩下还未迭代的元素遍历,用lamda表达式。
default void forEachRemaining(Consumer<? super E>
action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
用lamda表达式对迭代器剩下还未迭代的元素遍历。用关键字default修饰接口中的方法,可以定义方法体。
三、iterable接口的内部方法
public interface Iterable<T> {
//返回一个在一组 T 类型的元素上进行迭代的迭代器。
Iterator<T> iterator();
//用lamda表达式进行forEach遍历迭代器
default void forEach(Consumer<? super T>
action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
}
Iterable在方法中返回“迭代器”的Iterator对象。
四、Iterable与Iterator关系
为什么不直接把Iterator接口中的hasNext(),next()等方法放在Iterable接口中,其他类直接实现Iterable接口就可以了?JDK的写法是否是多此一举?
非也!
原因是有些集合类可能不止一种遍历方式,实现了Iterable的类可以再实现多个Iterator内部类,例如LinkedList中的ListItr和DescendingIterator两个内部类,就分别实现了双向遍历和逆序遍历。通过返回不同的Iterator实现不同的遍历方式,这样更加灵活。如果把两个接口合并,就没法返回不同的Iterator实现类了。