[java学习笔记]Iterator和Iterable接口

版权声明:转载请注明,谢谢。 https://blog.csdn.net/ciefer/article/details/52597829

    Iterator和Iterable都是java的迭代器接口,二者既有区别又有联系,下面从接口定义,实现和方法调用三方面分析两接口的关系和使用方法。

1.接口定义

1.1 Iterable

    Iterable包含在java.lang中,使用时不需要import,其定义如下

public interface Iterable<Item>{
    Iterator<Item> iterator();
}

    可以看出Iterable接口提供了iterator方法(注意大小写,和Iterator接口不同),该方法返回的是一个Iterator接口。这里需要说明的是方法是可以返回接口的,但在实际调用该方法时,真正返回的是实现这一接口的某个类的实例(后面会有举例说明)。


1.2 Iterator

    既然Iterable返回的是Iterator接口,那我们就来看看Iterator的定义。与Iterable不同的是,Iterator是包含在java.util.Iterator类中,因此使用时需要先import下

public interface Iterator<Item>{
   boolean hasnext();  #判断集合体是否到头
   Item next();        #返回下一项的值
   void remove();      #删除某项,本文不予讨论
}

    Iterator看着就比Iterable正常多了,三个方法都很好理解。


2.接口实现

    下面以stack为例,解释如何在一个新的collection中实现这两个接口。
import java.util.Iterator;
public class ArrayStack<Item> implements Iterable<Item>{
    private Item[] a = (Item[]) new Object[100];
    private int N = 0;
    public void push(Item item){}
    public Item pop(){}
    
    public Iterator<Item> iterator(){
        return new ArrayIterator();
    }
    private class ArrayIterator implements Iterator<Item>{
        private int i = 0;
        public boolean hasNext() {return i < N;}
        public Item next() {return a[i++];}
        public void remove() {}
    }
}

    需要注意的是,stack实现的是Iterable接口,并通过Iterable中的iterator方法(还是注意区分大小写),返回一个ArrayIterator类的对象,而ArrayIterator正是实现了Iterator方法的一个类,这就是前面说的方法返回接口,实际上是返回了一个实现了该接口的类的实例。这里可能会有人问,为什么一定要先实现Iterable接口,而不直接实现Iterator接口呢,这样多写一个内部类不是很麻烦吗? 
      其实理解起来也很容易,在网上看到一段解释说的很明白:

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

     出处:点击打开链接


3.接口方法调用

    Iterator调用的例子在网上就太多了,为了文章概念的完整性,这里仅列出最简单的两种调用。
ArrayStack<String> as = new ArrayStack<String>();
Iterator<String> i = as.iterator();
while(i.hasNext()){
    String s = i.next();
    StdOut.println(s);
}
上面是标准的调用Iterator进行遍历输出的例子,第二行代码可能会带来一些误解,看上去好像接口被实例化了,其实不然。我们知道接口是不能被实例化的,和上面方法返回接口类似,这里的“接口实例化”的其实是一个实现了这个接口的类的对象,换句话讲第二行等同于 
Iterator<String> i = new ArrayIterator();
     只不过ArrayIterator是一个内部的私有类,我们不能直接调用它,需要用iterator方法来完成这一过程。 
 

    除了上面的标准写法,还有一种简练的foreach语句,也就是某些人说的增强for语句:

for(String s: as){
    StdOut.println(s);
}

   p.s. 可以,这很python

猜你喜欢

转载自blog.csdn.net/ciefer/article/details/52597829