Java中迭代器

    由于Java中数据容器众多,而对数据容器的操作在很多时候都具有极大的共性,于是Java采用了迭代器为各种容器提供公共的操作接口。使用Java的迭代器iterator可以使得对容器的遍历操作完全与其底层相隔离,可以到达极好的解耦效果。

    迭代器的目的就是不用关心容器类型,而可以遍历序列中的对象。 客户端程序员不必知道或者关心该序列底层的结构。此外迭代器被称为轻量级对象,因为创建它的代价小。

public interface Iterable<T>

   Iterator<T> iterator() 
          Returns an iterator over a set of elements of type T

Collection接口拓展了接口Iterable,根据以上的对Iterable接口的定义可以发现,其要求实现其的类都提供一个返回迭代器Iterator<T>对象的方法。

迭代器Iterator<T>接口的的定义为:

Interface Iterator<E>
boolean  hasNext() 
          Returns true if the iteration has more elements.

 E  next() 
          Returns the next element in the iteration.

void  remove() 
          Removes from the underlying collection the last element returned by the iterator (optional operation).

注意:

  从以上的定义中可以发现,似乎Iterable()接口和Iterator()接口完全一致,没有任何区别。结合刚刚学习的内部类,可以发现这又是一个支持程序多样化的巧妙设计,充分的支持了多态和解耦。

迭代器是遍历Collection的工具,无论什么类型的Collection都可以用iterator来遍历。

例:

public class Test {
	public static void main(String[] args) {
		ArrayList<String> l = new ArrayList<String>();
		l.add("a");
		l.add("b");
		l.add("c");
		l.add("d");
		l.add("e");
		l.add("f");
		l.add("g");
		l.add("h");
		System.out.println(l);
		ListIterator<String> listIterator = l.listIterator();
		String s1 = listIterator.next();
		System.out.println("s1: " + s1);
		String s2 = listIterator.next();
		System.out.println("s2: " + s2);
		String s1Previous = listIterator.previous();
		System.out.println("s1Pre: " + s1Previous);
		String sPrevious2 = listIterator.previous();
		System.out.println("sPre2: " + sPrevious2);
	}
}

返回结果

[a, b, c, d, e, f, g, h]
s1: a
s2: b
s1Pre: b
sPre2: a

iterator的工作示意图:

153856_eQHK_2561483.png

iterator是这样工作的,首先声明的是iterator的cursor指向的是元素之间的间隔位置(如上图所示 Iterator1和Iterator的位置)
当调用iterator.next()时,官方文档是这样写的:
Returns the next element in the list and advances the cursor position.
意思是,返回当前指针的下一个元素,并且推进指针到下一个位置。

举个例子:
list.iterator()  // cursor处在图中Iterator1的位置
iterator.next() // 返回list的元素1也就是图中的List1, 然后cursor推进一个位置到Iterator2的位置,如此往复进行遍历

    客户端自身不维护遍历集合的"指针",所有的内部状态(如当前元素位置,是否有下一个元素)都由Iterator来维护,而这个Iterator由集合类通过工厂方法生成,因此,它知道如何遍历整个集合。 客户端从不直接和集合类打交道,它总是控制Iterator,向它发送"向前","向后","取当前元素"的命令,就可以间接遍历整个集合 。 

java.util.Iterator接口的定义: 
public interface Iterator { boolean hasNext(); Object next(); void remove(); } 

hasNext():遍历过程中,判定是否还有下一个元素。(从Collection对象的第一个元素开始)

next(): 遍历该元素。(即取出下一个元素)

remove(): 移除刚刚遍历过的元素。

在遍历下一个元素前,先判断其是否存在。对于想删除的元素,必须先遍历其,故 remove()方法总是接在 next()方法之后。

依赖前两个方法就能完成遍历,典型的代码如下: 
for(Iterator it = c.iterator(); it.hasNext(); ) { Object o = it.next(); // 对o的操作... }  
在JDK1.5中,还对上面的代码在语法上作了简化(但是限于只读,如果需要remove,还是直接使用iterator): 
// Type是具体的类型,如String。 for(Type t : c) { // 对t的操作... }   

每一种集合类返回的Iterator具体类型可能不同,Array可能返回ArrayIterator,Set可能返回SetIterator,Tree可能返回TreeIterator,但是它们都实现了Iterator接口,因此,客户端不关心到底是哪种Iterator,它只需要获得这个Iterator接口即可

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

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

转载于:https://my.oschina.net/u/3352105/blog/877876

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值