Iterable 接口
Iterable
接口是 Collection
接口的父接口,它表示实现类可以用迭代器遍历,因此 Collection 部分的所有实现类都可以使用 for-each loop。该接口的声明如下所示:
public interface Iterable<T> {
Iterator<T> iterator();
default void forEach(Consumer<? super T> action) {}
default Spliterator<T> spliterator() {}
}
另外,我们在使用 for-each loop 时,应该知道其只是一个语法糖。我们可以对下面示例代码的 .class 文件进行反编译:
List<String> strings = new ArrayList<>();
strings.add("A");
strings.add("B");
for (String s : strings) { // 语法糖
System.out.println(s);
}
$ java -jar cfr-0.150.jar Test.class --collectioniter false
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add("A");
arrayList.add("B");
Iterator iterator = arrayList.iterator(); // 迭代器
while (iterator.hasNext()) {
String string = (String)iterator.next();
System.out.println(string);
}
Iterator 接口
Iterator
接口即我们常说的迭代器,它的声明如下所示:
public interface Iterator<E> {
boolean hasNext();
/**
* 如果迭代器没有元素了,会抛出 NoSuchElementException
*/
E next();
/**
* 只能在调用 next() 后调用一次 remove(),如没有调用 next() 就调用
* remove(),或连续两次调用 remove(),都会抛出 IllegalStateException。
*/
default void remove() {
throw new UnsupportedOperationException("remove");
}
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
对于迭代器,最常见的总结是以下两点:
hasNext()
与next()
的固定搭配;- 调用
remove()
方法前,必须先调用next()
方法,且不能连续调用remove()
方法。
除了以上两点外,你还需要注意: Iterator
接口没有声明“添加”方法,即迭代器只能遍历和删除,而不能添加。官方解释是:迭代器并不能保证遍历是有序的,这与集合的实现类结构有关。