Iterator 和 Iterable 差别和联系

用Iterator模式实现遍历集合 

Iterator模式是用于遍历集合类的标准訪问方法。它能够把訪问逻辑从不同类型的集合类中抽象出来,从而避免向client暴露集合的内部结构。

比如,假设没有使用Iterator,遍历一个数组的方法是使用索引: for(int i=0; i<array.size(); i++) { ... get(i) ... }

而訪问一个链表(LinkedList)又必须使用while循环: while((e=e.next())!=null) { ... e.data() ... }

以上两种方法client都必须事先知道集合的内部结构,訪问代码和集合本身是紧耦合。无法将訪问逻辑从集合类和client代码中分离出来,每一种集合相应一种遍历方法,client代码无法复用。

更恐怖的是,假设以后须要把ArrayList更换为LinkedList,则原来的client代码必须所有重写。

解决以上问题。Iterator模式总是用同一种逻辑来遍历集合: for(Iterator it = c.iterater(); it.hasNext(); ) { ... }

        奥秘在于client自身不维护遍历集合的"指针"。全部的内部状态(如当前元素位置,是否有下一个元素)都由Iterator来维护,而这个Iterator由集合类通过工厂方法生成。因此,它知道怎样遍历整个集合。

client从不直接和集合类打交道,它总是控制Iterator,向它发送"向前","向后"。"取当前元素"的命令,就能够间接遍历整个集合。

首先看看java.util.Iterator接口的定义:

public interface Iterator { boolean hasNext(); Object next(); void remove(); }

依赖前两个方法就能完毕遍历,典型的代码例如以下:

for(Iterator it = c.iterator(); it.hasNext(); ) { Object o = it.next(); // 对o的操作... }

每一种集合类返回的Iterator详细类型可能不同,Array可能返回ArrayIterator,Set可能返回 SetIterator。Tree可能返回TreeIterator,可是它们都实现了Iterator接口。因此,client不关心究竟是哪种 Iterator,它仅仅须要获得这个Iterator接口就可以。这就是面向对象的威力。

全部集合类都实现了 Collection 接口,而 Collection 继承了 Iterable 接口。

/**
 * Implementing this interface allows an object to be the target of
 * the "foreach" statement.
 *
 * @param <T> the type of elements returned by the iterator
 *
 * @since 1.5
 */
public interface Iterable<T> {

    /**
     * Returns an iterator over a set of elements of type T.
     *
     * @return an Iterator.
     */
    Iterator<T> iterator();
}

而在详细的实现类中(比方 ArrayList),则在内部维护了一个 Itr 内部类。该类继承了 Iterator 接口,它的hasNext() 和 next() 方法是和 ArrayList 实现相耦合的。

当调用 ArrayList 对象的 iterator() 方法的时候,返回该类 Itr 的一个实例,从而实现遍历 ArrayList 的功能。

public Iterator<E> iterator() {
        return new Itr();
    }

    /**
     * An optimized version of AbstractList.Itr
     */
    private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;

        public boolean hasNext() {
            return cursor != size;
        }

        @SuppressWarnings("unchecked")
        public E next() {
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }

        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                ArrayList.this.remove(lastRet);
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

为什么一定要去实现Iterable这个接口呢?为什么不直接实现Iterator接口呢?

看一下JDK中的集合类,比方List一族或者Set一族,都是实现了Iterable接口。但并不直接实现Iterator接口。 细致想一下这么做是有道理的。

由于Iterator接口的核心方法next()或者hasNext() 是依赖于迭代器的当前迭代位置的。

假设Collection直接实现Iterator接口。势必导致集合对象中包括当前迭代位置的数据(指针)。 当集合在不同方法间被传递时,由于当前迭代位置不可预置,那么next()方法的结果会变成不可预知。

除非再为Iterator接口加入一个reset()方法,用来重置当前迭代位置。 但即时这样,Collection也仅仅能同一时候存在一个当前迭代位置

而Iterable则不然,每次调用都会返回一个从头開始计数的迭代器。 多个迭代器是互不干扰的。

时间: 2025-01-04 21:45:08

Iterator 和 Iterable 差别和联系的相关文章

【转】Java迭代:Iterator和Iterable接口

Java迭代 : Iterator和Iterable接口 从英文意思去理解 Iterable :故名思议,实现了这个接口的集合对象支持迭代,是可迭代的.able结尾的表示 能...样,可以做.... Iterator:   在英语中or 结尾是都是表示 ...样的人 or ... 者.如creator就是创作者的意思.这里也是一样:iterator就是迭代者,我们一般叫迭代器,它就是提供迭代机制的对象,具体如何迭代,都是Iterator接口规范的. Iterable 一个集合对象要表明自己支持迭

java中的Iterator和Iterable

1.Iterable接口在java.lang包中:Iterator接口在java.util包中 2.Iterable中只有一个方法,那就是返回一个Iterator迭代器:Iterator<T> iterator() 而Iterator中有关于迭代器的核心功能,next(),hasNext(),remove() 所以说,Iterable接口实现后的功能是“返回”一个迭代器,而Iterator接口实现后的功能是“使用”一个迭代器 3.在java.util中的容器类基本都实现了Iterable ,下

python generator iterator和iterable object

1 iterable object list.dict.set.tuple.file(在每行上iterate)等都是iterable object,但是它们不是iterator.但是它们可以转换成iterator,通过两种方式: 第一,显式的使用iter()函数; 第二,隐式的使用for 2 iterator iterator也是iterable的. 3 generator 3.1 种类 有两种类型的generators 3.2 使用yield来返回的函数形式的generator 使用yield

大杂烩 -- Iterator 和 Iterable 区别和联系

基础大杂烩 -- 目录 用Iterator模式实现遍历集合  Iterator模式是用于遍历集合类的标准访问方法.它可以把访问逻辑从不同类型的集合类中抽象出来,从而避免向客户端暴露集合的内部结构. 例如,如果没有使用Iterator,遍历一个数组的方法是使用索引: for(int i=0; i<array.size(); i++) { ... get(i) ... } 而访问一个链表(LinkedList)又必须使用while循环: while((e=e.next())!=null) { ...

Iterator 和 Iterable 区别和联系

用Iterator模式实现遍历集合  Iterator模式是用于遍历集合类的标准访问方法.它可以把访问逻辑从不同类型的集合类中抽象出来,从而避免向客户端暴露集合的内部结构. 例如,如果没有使用Iterator,遍历一个数组的方法是使用索引: for(int i=0; i<array.size(); i++) { ... get(i) ... } 而访问一个链表(LinkedList)又必须使用while循环: while((e=e.next())!=null) { ... e.data() ..

Iterator、Iterable接口的使用及详解

Java集合类库将集合的接口与实现分离.同样的接口,可以有不同的实现. Java集合类的基本接口是Collection接口.而Collection接口必须实现Iterator接口. 以下图表示集合框架的接口,java.lang以及java.util两个包里的.其他部分可以从左向右看,比如Collection的Subinterfaces有List,Set以及Queue等. package java.util; /** * An iterator over a collection. Iterato

Java中Iterator与Iterable的区别

Iterable的定义: java.lang包 /** * Implementing this interface allows an object to be the target of * the "foreach" statement. * * @param <T> the type of elements returned by the iterator * * @since 1.5 */ public interface Iterable<T> { /

iterator与iterable

用Iterator模式实现遍历集合Iterator模式是用于遍历集合类的标准访问方法.它可以把访问逻辑从不同类型的集合类中抽象出来,从而避免向客户端暴露集合的内部结构.例如,如果没有使用Iterator,遍历一个数组的方法是使用索引:for(int i=0; i<array.size(); i++) { ... get(i) ... } 而访问一个链表(LinkedList)又必须使用while循环:while((e=e.next())!=null) { ... e.data() ... } 以

Python 中 Iterator和Iterable的区别

(转载:http://blog.csdn.net/passionkk/article/details/49929887) Python中 list,truple,str,dict这些都可以被迭代,但他们并不是迭代器.为什么? 因为和迭代器相比有一个很大的不同,list/truple/map/dict这些数据的大小是确定的,也就是说有多少事可知的.但迭代器不是,迭代器不知道要执行多少次,所以可以理解为不知道有多少个元素,每调用一次next(),就会往下走一步,是惰性的. 判断是不是可以迭代,用It