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 falseArrayList<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 接口没有声明“添加”方法,即迭代器只能遍历和删除,而不能添加。官方解释是:迭代器并不能保证遍历是有序的,这与集合的实现类结构有关。
