关于Iterable与Iterator的那些事

来自Wikioe
跳到导航 跳到搜索


Iterable

Iterable 接口:
用于支持foreach的循环:Iterable接口的“iterator()”方法,用于返回一个Iterator对象。(所有实现Iterable接口的集合都可以使用foreach循环进行遍历)

package java.lang;
...
public interface Iterable<T> {

    Iterator<T> iterator();

    default void forEach(Consumer<? super T> action) {
        // 验证action是否为null,如果action为null,则抛出NullPointerException
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }

    default Spliterator<T> spliterator() {
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}

Iterable有三个方法,分别是

  1. Iterator iterator():
    返回T类型的元素上的一个迭代器
  2. default void forEach(Consumer action):
    (JDK 1.8后新增)该方法是循环输出,对内部元素进行遍历,并对元素进行指定的操作(Consumer是一个函数式接口,可以使用lambda)。例如:
    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
     numbers.forEach(integer -> System.out.println(integer));
    
  3. default Spliterator spliterator():
    (JDK 1.8后新增)该方法提供了一个可以并行遍历元素的迭代器,以适应现在cpu多核时代并行遍历的需求。(简单说:分割,增加并行处理能力)

Iterator

Iterator 接口:
主要用来操作java里的集合对象(collection)。迭代器提供了统一的语法进行集合对象(collection)遍历操作,无需关心集合对象的内部实现方式。(Iterator只能向前移动,无法回退。)

package java.util;
...
public interface Iterator<E> {

    boolean hasNext();

    E next();

    default void remove() {
        throw new UnsupportedOperationException("remove");
    }

    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}
  1. boolean hasNext():
    如果被迭代遍历的集合还没有被遍历完,返回True
  2. E next():
    返回集合里面的下一个元素
  3. void remove():
    删除集合里面上一次next()方法返回的元素
  4. void forEachRemaining(Consumer action):
    (JDK 1.8后新增)使用Lambda表达式来遍历集合元素。例如:
    List<String> arr=new ArrayList<>();
    arr.add("hello");
    arr.add(("world"));
    arr.iterator().forEachRemaining(str-> System.out.println(str));
    

ListIterator

ListIterator :继承自 Iterator 接口。只在 List 上进行使用,可以双向迭代

package java.util;

public interface ListIterator<E> extends Iterator<E> {

    boolean hasNext();

    E next();

    boolean hasPrevious();

    E previous();

    int nextIndex();

    int previousIndex();

    void remove();

    void set(E e);

    void add(E e);
}
  1. add(E e):向 List 中添加元素。
  2. remove():从 List 中删除 next() 或 previous() 返回的最后一个元素。
  3. set(E e):使用指定元素来覆盖 next() 或 previous() 返回的最后一个元素。
  4. hasNext():如果还没有到达 List 的末尾,则返回 true,否则返回 false。
  5. next():返回 List 中的下一个元素。
  6. nextIndex():返回下一元素的下标。
  7. hasPrevious():如果还没有到达 List 的开头,则返回 true,否则返回 false。
  8. previous():返回 List 的上一个元素。
  9. previousIndex():返回上一元素的下标。

Iterator 与 ListIterator

  1. Iterator:可以用于任意集合 —— List、Map、Queue、Set等;只能向前移动,无法回退;
  2. ListIterator:只能应用于 List;支持双向迭代;

Iterable 与 Iterator

forEachRemaining 与 forEach

forEach:(Iterable)

default void forEach(Consumer<? super T> action) {
    Objects.requireNonNull(action);
    for (T t : this) {
        action.accept(t);
    }
}

forEachRemaining:(Iterator)

default void forEachRemaining(Consumer<? super E> action) {
    Objects.requireNonNull(action);
    while (hasNext())
        action.accept(next());
}
  • 同:都是JDK1.8中引入的接口的默认方法,都可以用于遍历集合;
  • 异:
    1. forEach()方法内部使用的是增强for循环;forEachRemaining()方法内部是通过使用Iterator本身的遍历方法
    2. forEach()方法可以多次调用;forEachRemaining()方法第二次调用不会做任何操作(hasNext判断没有了下一个元素)。

如何使 Iterator 重新回到起点

使用一个iterator时遍历到集合末尾,如何回到开始再次使用next进行循环:重新初始化

  • (如果是 ListIterator,可以双向遍历)
    List<String> list=new ArrayList<String>();
    list.add("hello");
    list.add("world");
    list.add("!");
		
    Iterator<String> iterator;
    for(int i=0;i<2;i++){
        iterator=list.iterator();
        while(iterator.hasNext()){
            System.err.println(iterator.next());
        }
    }

关于集合使用 Iterable 与 Iterator

Java中的 Collection:

  1. 可以使用 foreach 遍历:【Collection 接口扩展了 Iterable 接口】。
  2. 可以使用 Iterator 遍历:【通过“iterator()”返回了一个 Iterator 接口实现类的对象(一般用内部类实现)】