欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java集合(1)——Iterable接口和Iterator接口

程序员文章站 2024-02-17 17:01:58
...

集合类图

Java集合(1)——Iterable接口和Iterator接口

  • Iterable 是Java.lang包下的接口
  • Iterabtor是java.util包下的接口
  • Iterable接口包装了Iterator接口

java.lang.Iterable接口

Java集合(1)——Iterable接口和Iterator接口

官方文档介绍:

Implementing this interface allows an object to be the target of the “for-each loop” statement
翻译:Iterable接口作为超级接口,这个接口只有一个方法,该方法返回值类型是Iterator,方法名称为iterator() ,实现这个接口的对象可称为“for–each”语句的目标

  • Iterable接口中的方法 (在jdk1.8中又增添了两个default方法)

Java集合(1)——Iterable接口和Iterator接口

public interface Iterable<T> {

    Iterator<T> iterator();

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

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

java.util.Iterator接口

Java集合(1)——Iterable接口和Iterator接口

官方文档介绍:

An iterator over a collection. Iterator takes the place of Enumeration in the Java Collections Framework. Iterators differ from enumerations in two ways:
(1) Iterators allow the caller to remove elements from the underlying collection during the iteration with well-defined semantics.
(2) Method names have been improved.
翻译:集合上的迭代器。在集合框架中,Iterator迭代器取代了Enumeration。Iterator与Enumeration有两点不同
(1) 迭代器允许调用者在迭代过程中从定义良好的语义中删除底层集合中的元素。
(2) 名称比原来变短了。(可能大家都不愿意打那么长的名字。。。)

  • Iterator接口中的方法

Java集合(1)——Iterable接口和Iterator接口

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());
    }
}
  • 通过调用next()方法,可以逐个访问集合中的每个元素,但是如果到达了集合的末尾,next()方法将会抛出一个NoSuchElementException异常,因此需要在调用next()方法钱先调用hashNext()方法判断是否还有元素
  • Iterator接口的remove方法将会删除上次调用next()方法时返回的元素,next()方法和remove()方法的调用具有相互依赖性。如果调用remove()之前没有调用next()方法将是不合法的。如果这样做,将会抛出一个IllegalStateException异常
  • 每一种集合类返回的Iterator具体类型可能不同,Array可能返回ArrayIterator,Set可能返回SetIterator,Tree可能返回TreeIterator。但是他们都实现了Iterator接口。因此,客户端不需要关心到底是哪种Iterator,它只需要获得这个Iterator接口即可,这就是面向对象的威力。

使用Iterator的好处

  • 在不使用Iterator时,遍历集合:
    for(int i = 0; i < list.size(); i++){

    }
  • 在使用Iterator时,遍历集合:
    Iterator i = nums.iterator();
    while (iterator.hasNext()){
        System.out.println(iterator.next());
    }

Iterable接口与Iterator接口之间的关系

  • 在集合中很多类都实现了Iterable接口。因为Collection是Iterable接口的子接口,集合中很多接口都继承Collection接口,出了Map接口
  • Iterator()是用于遍历集合类的标准访问方法。它可以把访问逻辑从不同类型的集合类中抽象出来,从而避免像客户端暴露集合的内部结构
  • 那为什么一定要实现Iterable接口,为什么不直接实现Iterator接口呢?
    • 看一下JDK中的集合类,比如List和Set,都实现了Iterable接口,但是并没有实现Iterator接口。仔细想一下这么做是有道理的。
    • 因为Iterator接口的核心方法next()或者hasNext()是依赖于迭代器的当前迭代位置的。如果Collection直接实现iterator接口,势必导致集合对象中包含当前迭代位置的数据(指针)。当集合在不同方法间被传递时,由于当前迭代为止不可知,那么next()方法的结果就会变得不可知。除非再为Iterator接口添加一个reset()方法,用来重置当前迭代位置。但即使是这样,Collection也只能同时存在一个当前迭代位置。而Iterable接口则不然,每次调用都会返回一个从头开始计数的迭代器。多个迭代器之间是互不干扰的。