foreach 循环

来源:互联网 发布:招聘php 编辑:程序博客网 时间:2024/05/18 21:41

foreach循环权威总结

-* 原文地址 http://docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html*

集合迭代的代码实现往往非常臃肿。考虑下面这个例子,它遍历定时器任务并取消它们:

void cancelAll(Collection<TimerTask> c) {    for (Iterator<TimerTask> i = c.iterator(); i.hasNext(); )        i.next().cancel();}

这个迭代器的使用非常繁琐也容易导致错误。因为迭代器在循环中出现了3次,后面两次都可能出错。而for-each循环解决了这些问题:

void cancelAll(Collection<TimerTask> c) {    for (TimerTask t : c)        t.cancel();}

其中冒号读作“in”。这个循环读作“for each TimerTask t in c.”for-each循环和泛型完美结合,此时我们不需要声明迭代器,因此也不需要为它提供泛型定义(实际上编译器为我们实现了这些)。所以它不但提供了类型安全,也去掉了复杂的语法 。

下面是嵌套循环中容易出现的另一个错误:

List suits = ...;List ranks = ...;List sortedDeck = new ArrayList();// BROKEN - throws NoSuchElementException!for (Iterator i = suits.iterator(); i.hasNext(); )    for (Iterator j = ranks.iterator(); j.hasNext(); )        sortedDeck.add(new Card(i.next(), j.next()));

如果你没有发现这个bug请不要灰心,许多专家级的程序员也会时不时犯这个错误。仔细检查会发现suits的next方法被调用了太多次。要解决这个问题可以采用下列方法:

// Fixed, though a bit uglyfor (Iterator i = suits.iterator(); i.hasNext(); ) {    Suit suit = (Suit) i.next();    for (Iterator j = ranks.iterator(); j.hasNext(); )        sortedDeck.add(new Card(suit, j.next()));}

那这和for-each循环有什么关系呢?实时上它可以完美解决这个问题:

for (Suit suit : suits)    for (Rank rank : ranks)        sortedDeck.add(new Card(suit, rank));

for-each对数组同样有效:

// Returns the sum of the elements of aint sum(int[] a) {    int result = 0;    for (int i : a)        result += i;    return result;}

那么我们什么时候采用for-each循环呢?实际上我们应该尽可能使用它。它可以让代码更加完美。但是它也有自己的缺点。因为for-each隐藏了迭代器,因此我们无法调用remove方法以删除元素,也无法在循环中替换元素。同时它也不适合并行遍历多个集合。
事实上for-each的设计者们精心考虑过这些问题,目前的for-each设计是一个简洁易用而且足以覆盖大多数情况的解决方案。

原创粉丝点击