java for-each的使用场景和使用方法

   使用for-each的可以是一个数组,或者是实现Iterable这个接口的对象(Collection继承了这个接口,所有集合类都可以使用for-each)

   既然for循环能遍历一个数组或者集合,那么为什么还会有一个for-each做遍历呢?下面(参考了jdk1.8api)举例说明:

for循环遍历每一个TimerTask类型的元素,然后调用其cancel方法。

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

  你能从上面的代码发现有什么问题吗?如上确实能实现遍历操作集合元素的功能,但是迭代器变量在每个循环中出现三次,for-each构造摆脱了这样的问题。

void cancelAll(Collection c) {
    for (TimerTask t : c)
        t.cancel();
}
  冒号(:)读作“in”,上面的循环读作“对于c中的每个TimerTask t”。正如您所看到的,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()));
  问题是“外部”集合(套装)上被调用了太多次。它在外部和内部集合的内部循环中被调用,这是错误的。
为了解决这个问题,在外循环的范围内添加一个变量来保存这个套装:


// Fixed, though a bit ugly
for (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构造也适用于数组,它隐藏了索引变量而不是迭代器。以下方法返回int数组中值的总和:

>// Returns the sum of the elements of a>
int sum(int[] a) {
    int result = 0;
    for (int i : a)
        result += i;
    return result;
}
  总结:那么你应该什么时候使用for-each循环呢?任何时候都可以。它真的美化你的代码。但不是在任何地方使用它。例如,考虑expurgate方法。该程序需要访问迭代器才能删除当前元素。for-each循环隐藏了迭代器,所以你不能调用remove。因此,for-each循环不能用于遍历时有删除操作。同样,它不适用于需要在遍历列表或数组时替换元素的循环。最后,它不能用于必须并行迭代多个集合的循环。

你可能感兴趣的:(java)