Iterable 接口

Iterable 接口是 Collection 接口的父接口,它表示实现类可以用迭代器遍历,因此 Collection 部分的所有实现类都可以使用 for-each loop。该接口的声明如下所示:

  1. public interface Iterable<T> {
  2. Iterator<T> iterator();
  3. default void forEach(Consumer<? super T> action) {}
  4. default Spliterator<T> spliterator() {}
  5. }

另外,我们在使用 for-each loop 时,应该知道其只是一个语法糖。我们可以对下面示例代码的 .class 文件进行反编译:

  1. List<String> strings = new ArrayList<>();
  2. strings.add("A");
  3. strings.add("B");
  4. for (String s : strings) { // 语法糖
  5. System.out.println(s);
  6. }
  1. $ java -jar cfr-0.150.jar Test.class --collectioniter false
  2. ArrayList<String> arrayList = new ArrayList<String>();
  3. arrayList.add("A");
  4. arrayList.add("B");
  5. Iterator iterator = arrayList.iterator(); // 迭代器
  6. while (iterator.hasNext()) {
  7. String string = (String)iterator.next();
  8. System.out.println(string);
  9. }

Iterator 接口

Iterator 接口即我们常说的迭代器,它的声明如下所示:

  1. public interface Iterator<E> {
  2. boolean hasNext();
  3. /**
  4. * 如果迭代器没有元素了,会抛出 NoSuchElementException
  5. */
  6. E next();
  7. /**
  8. * 只能在调用 next() 后调用一次 remove(),如没有调用 next() 就调用
  9. * remove(),或连续两次调用 remove(),都会抛出 IllegalStateException。
  10. */
  11. default void remove() {
  12. throw new UnsupportedOperationException("remove");
  13. }
  14. default void forEachRemaining(Consumer<? super E> action) {
  15. Objects.requireNonNull(action);
  16. while (hasNext())
  17. action.accept(next());
  18. }
  19. }

对于迭代器,最常见的总结是以下两点:

  • hasNext()next() 的固定搭配;
  • 调用 remove() 方法前,必须先调用 next() 方法,且不能连续调用 remove() 方法。

除了以上两点外,你还需要注意: Iterator 接口没有声明“添加”方法,即迭代器只能遍历和删除,而不能添加官方解释是:迭代器并不能保证遍历是有序的,这与集合的实现类结构有关。