源码分析之Iterable

  当想要遍历集合时,Java为我们提供了多种选择,通常有以下三种写法:

  • for循环

  for循环,就是根据下标来获取元素,这个特性与数组十分吻合。

for (int i = 0, len = strings.size(); i < len; i++) {
    System.out.println(strings.get(i));
}
  • foreach循环

  foreach则主要对类似链表的结构提供遍历支持,链表没有下标。foreach遍历实际上使用的是Iterator. 可通过 javap -verbose Test.class 查看具体实现

for (String var : strings) {
    System.out.println(var);
}
  • Iterator
Iterator iterator = strings.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}

 

Iterable

  Iterable接口是Java集合框架的顶级接口。Iterable是迭代器的意思,作用是为集合类提供for-each循环的支持。也就是说,如果想让一个Java对象支持foreach,只要实现Iterable接口,然后就可以像集合那样,通过Iterator iterator = strings.iterator()方式,或者使用foreach,进行遍历了。源码如下:

public interface Iterable<T> {
    // 返回一个内部元素为T类型的顺序迭代器
    Iterator<T> iterator();

    // 对Iterable中的元素进行指定的操作
    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }

    // 返回一个内部元素为T类型的并行迭代器
    default Spliterator<T> spliterator() {
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}

Iterator

  Iterator为Java中的迭代器对象,是能够对List这样的集合进行迭代遍历的底层依赖。Iterator通过以下两个方法定义了对集合迭代访问的方法,而具体的实现方式依赖于不同的实现类,具体的集合类实现Iterator接口中的方法以实现迭代。

public interface Iterator<E> {
    // 判断一个对象集合是否还有下一个元素
    boolean hasNext();

    // 获取下一个元素
    E next();

    // 删除最后一个元素。默认是不支持的,因为在很多情况下其结果不可预测,比如数据集合在此时被修改
    default void remove(){...}

    // 主要将每个元素作为参数发给action来执行特定操作
    default void forEachRemaining(Consumer<? super E> action){...}
}

  为什么不直接将hasNext(),next()方法放在Iterable接口中,其他类直接实现就可以了?
  原因是有些集合类可能不止一种遍历方式,实现了Iterable的类可以再实现多个Iterator内部类,例如LinkedList中的ListItr和DescendingIterator两个内部类,就分别实现了双向遍历和逆序遍历。通过返回不同的Iterator实现不同的遍历方式,这样更加灵活。

posted @ 2020-11-25 17:29  鄙人取个名字好难  阅读(251)  评论(0编辑  收藏  举报