• Iterator 和 Iterable 区别和联系


    转:http://blog.csdn.net/zq602316498/article/details/39337899

    用Iterator模式实现遍历集合 

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

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

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

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

            更恐怖的是,如果以后需要把ArrayList更换为LinkedList,则原来的客户端代码必须全部重写。

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

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

            客户端从不直接和集合类打交道,它总是控制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接口,因此,客户端不关心到底是哪种 Iterator,它只需要获得这个Iterator接口即可,这就是面向对象的威力。 

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

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. /** 
    2.  * Implementing this interface allows an object to be the target of 
    3.  * the "foreach" statement. 
    4.  * 
    5.  * @param <T> the type of elements returned by the iterator 
    6.  * 
    7.  * @since 1.5 
    8.  */  
    9. public interface Iterable<T> {  
    10.   
    11.     /** 
    12.      * Returns an iterator over a set of elements of type T. 
    13.      * 
    14.      * @return an Iterator. 
    15.      */  
    16.     Iterator<T> iterator();  
    17. }  

            而在具体的实现类中(比如 ArrayList),则在内部维护了一个 Itr 内部类,该类继承了 Iterator 接口,它的hasNext() 和 next() 方法是和 ArrayList 实现相耦合的。当调用 ArrayList 对象的 iterator() 方法的时候,返回该类 Itr 的一个实例,从而实现遍历 ArrayList 的功能。

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. public Iterator<E> iterator() {  
    2.         return new Itr();  
    3.     }  
    4.   
    5.     /** 
    6.      * An optimized version of AbstractList.Itr 
    7.      */  
    8.     private class Itr implements Iterator<E> {  
    9.         int cursor;       // index of next element to return  
    10.         int lastRet = -1; // index of last element returned; -1 if no such  
    11.         int expectedModCount = modCount;  
    12.   
    13.         public boolean hasNext() {  
    14.             return cursor != size;  
    15.         }  
    16.   
    17.         @SuppressWarnings("unchecked")  
    18.         public E next() {  
    19.             checkForComodification();  
    20.             int i = cursor;  
    21.             if (i >= size)  
    22.                 throw new NoSuchElementException();  
    23.             Object[] elementData = ArrayList.this.elementData;  
    24.             if (i >= elementData.length)  
    25.                 throw new ConcurrentModificationException();  
    26.             cursor = i + 1;  
    27.             return (E) elementData[lastRet = i];  
    28.         }  
    29.   
    30.         public void remove() {  
    31.             if (lastRet < 0)  
    32.                 throw new IllegalStateException();  
    33.             checkForComodification();  
    34.   
    35.             try {  
    36.                 ArrayList.this.remove(lastRet);  
    37.                 cursor = lastRet;  
    38.                 lastRet = -1;  
    39.                 expectedModCount = modCount;  
    40.             } catch (IndexOutOfBoundsException ex) {  
    41.                 throw new ConcurrentModificationException();  
    42.             }  
    43.         }  
    44.   
    45.         final void checkForComodification() {  
    46.             if (modCount != expectedModCount)  
    47.                 throw new ConcurrentModificationException();  
    48.         }  
    49.     }  

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

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

            因为Iterator接口的核心方法next()或者hasNext() 是依赖于迭代器的当前迭代位置的。 如果Collection直接实现Iterator接口,势必导致集合对象中包含当前迭代位置的数据(指针)。 当集合在不同方法间被传递时,由于当前迭代位置不可预置,那么next()方法的结果会变成不可预知。 除非再为Iterator接口添加一个reset()方法,用来重置当前迭代位置。 但即时这样,Collection也只能同时存在一个当前迭代位置。 而Iterable则不然,每次调用都会返回一个从头开始计数的迭代器(新的迭代器)。 多个迭代器是互不干扰的

     
     
  • 相关阅读:
    [Cerc2013]Magical GCD
    UVA 1393 Highways
    UVA 10214 Trees in a Wood
    [SDOI2010]大陆争霸
    Oracle逻辑读详解
    DBA_2PC_PENDING (转)
    oracle autotrace使用
    升级oracle 9i到10g
    VMware 虚拟机中添加新硬盘的方法(转载)
    ERROR 2002 (HY000): Can’t connect to local MySQL server through socket ‘/var mysql (转)
  • 原文地址:https://www.cnblogs.com/wxdlut/p/5848676.html
Copyright © 2020-2023  润新知