迭代器

任何容器都必须有方法可以将东西放进去,然后有方法将东西取出来。毕竟,存放事物是
容器最基本的工作。对于 ArrayList,add()是插入对象的方法,而 get()是取出元素的方
法之一。ArrayList 很灵活,可以随时选取任意元素,或使用不同的下标一次选取多个元素。


如果你从更高层的角度思考,会发现这里有个缺点:要使用容器必须知道其中元素确切的
类型。起初看起来这没什么不好,但是考虑下面的情况:如果原本是使用 ArrayList,但是
后来考虑到容器的特点,你想换用 Set,应该怎么做?或者你打算写通用的代码,它只是使
用容器,不知道或不关心容器的类型,那么如何才能不重写代码就可以应用于不同类型的
容器呢?


迭代器的概念(也是一种设计模式)可以用来达成此目的。迭代器是一个对象,它的工作
是遍历并选择序列中的对象。客户端程序员不关心序列底层的结构。此外,迭代器通常被
称为“轻量级”对象:创建它的代价小。因此,经常可以见到对迭代器有些奇怪的限制。
例如,某些迭代器只能单向移动。


Java 的 Iterator 就是迭代器受限制的例子,它只能用来:


1. 使用方法 iterator()要求容器返回一个 Iterator。第一次调用 Iterator 的 next()
方法时,它返回序列的第一个元素。
2.使用 next()获得序列中的下一个元素。
3.使用 hasNext()检查序列中是否还有元素。
4.使用 remove()将上一次返回的元素从迭代器中移除。


Iterator 能做的也就是这些了。它是迭代器最简单的实现,但是已经很有用了(而且还有
为 List 设计的更强大的 ListIterator)。为观察它的工作方式,我们先复习
CatsAndDogs.java 程序。原先的版本是用方法 get()来选择每个元素,下面例子是使用
Iterator:


//: c11:CatsAndDogs2.java
// Simple container with Iterator.
package c11; 
import com.bruceeckel.simpletest.*; 
import java.util.*; 


public class CatsAndDogs2 { 
private static Test monitor = new Test(); 
public static void main(String[] args) { 
    List cats = new ArrayList();
for(int i = 0; i < 7; i++)
      cats.add(new Cat(i)); 
    Iterator e = cats.iterator();
while(e.hasNext())
      ((Cat)e.next()).id(); 
  }
} ///:~


可以看到,程序最后几行不再使用 for 循环,而是使用 Iterator 遍历整个序列。有了 Iterator
就不必为容器中元素的数量操心,由 hasNext()和 next()为你照看着。


下面是创建一个通用的打印方法的例子:


//: c11:Printer.java
// Using an Iterator.
import java.util.*; 


public class Printer {
static void printAll(Iterator e) { 
while(e.hasNext())
      System.out.println(e.next()); 
  }
} ///:~


请仔细观察 printAll()方法。注意,其中没有关于序列类型的信息,只有一个迭代器
Iterator,而且对于序列,知道此 Iterator 就足够了:通过它可以取得下一个对象,还可
以知道是否到达了序列的底部。像这种“一次取出容器中的所有元素,然后一个一个进行
单独处理”的思想是很有用的,并将贯穿全书。


这个例子间接地使用了 Object.toString()方法,因而更具通用性。方法 println()被所有
基本类型和 Object 都重载过;对每种情况,都能自动调用相应的 toString()方法生成
String。


虽然不必要,但你仍然可以明确地作类型转换,效果与调用 toString()相同:


System.out.println((String)e.next()); 


通常 Object 提供的方法并不能满足需求,所以又要考虑类型转换的问题了。你得假设你已
经取得了某个特定类型的序列的 Iterator,并将对结果对象作类型转换(如果类型错误会
得到一个运行期异常)。


我们可以通过打印 Hamster 试试看:


//: c11:Hamster.java


public class Hamster {
private int hamsterNumber;
public Hamster(int hamsterNumber) { 
this.hamsterNumber = hamsterNumber; 
  }
public String toString() { 
return "This is Hamster #" + hamsterNumber; 
  }
} ///:~
//: c11:HamsterMaze.java
// Using an Iterator.
import com.bruceeckel.simpletest.*; 
import java.util.*; 


public class HamsterMaze { 
private static Test monitor = new Test(); 
public static void main(String[] args) { 
    List list = new ArrayList();
for(int i = 0; i < 3; i++)
      list.add(new Hamster(i)); 
    Printer.printAll(list.iterator()); 
    monitor.expect(new String[] { 
"This is Hamster #0",
"This is Hamster #1",
"This is Hamster #2"
    });
  }
} ///:~
可以编写 printAll(),使它接受一个 Collection 对象为参数,以代替 Iterator,但是后者有

更好的去耦性。


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值