【笔记58】for-each循环优先于传统的for循环

对于遍历数组或者集合的元素来说,一般我们都会想到用传统的for循环,要么使用数组下标进行索引,要么使用集合的迭代器进行遍历,迭代器和索引变量在每个循环中出现三次,其中有两次非常容易出现错误,一旦出现错误,有可能编译器不能发现错误。

在java1.5中发行版本中引入的for-each循环,其中隐藏了迭代器或者索引变量,避免混乱和出错的可能。观察如下代码:

//花色
public enum Suit {
    CLUB,DIAMOND,HEART,SPARE
}
//大小
public enum Rank {
    ACE,DEUCE,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE,TEN,JACK,QUEEN,KING
}


Collection<Suit> suits = Arrays.asList(Suit.values());
Collection<Rank> ranks = Arrays.asList(Rank.values());
List<Card> deck = new ArrayList<Card>();
for (Iterator<Suit> i = suits.iterator(); i.hasNext(); )
       for (Iterator<Rank> j = ranks.iterator(); j.hasNext(); )
              deck.add(new Card(i.next(), j.next()));

此程序想打印出一副没有大小王的牌,用迭代器进行遍历。但是打印出来是错误的结果:

CLUB+ACE 
DIAMOND+DEUCE 
HEART+THREE 
SPARE+FOUR 

是因为程序在里面进行了遍历,两个循环进行每一次遍历之后,内外层都会进行遍历。 
当外层的循环比内层的循环的次数更小时,会抛出NoSuchElementException的异常。

优化方案1:

for (Iterator<Suit> i = suits.iterator(); i.hasNext(); ) {
       Suit suit = i.next();
       for (Iterator<Rank> j = ranks.iterator(); j.hasNext(); )
              deck.add(new Card(suit, j.next()));
}

优化方案2:

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

for-each不仅可在集合和数组上迭代,而且还可在任何实现了Iterable接口的对象上迭代。接口Iterablel有一个简单的方法,随for-each一起加入平台,接口如下:

public interface Iterable<E> {
       // Returns an iterator over the elements in this iterable
       Iterator<E> iterator();
}

总之,与传统的for循环相比,在简洁及防错方面,for-each循环有着传统for循环无法比拟的优势,且没有性能损耗,应该尽可能的使用for-each循环。但是,有三种普遍情况无法使用for-each循环:
1、过滤-如果需要在集合上遍历且移去选定的元素,就要使用显式的迭代,并调用它的remove方法。
2、转换-如果需要在list或数组上遍历且要替换部分或所有的元素值,则需要list的迭代器或数组的索引去设置这些值。
3、平行迭代-如果需要并行的遍历多个集合,则需要显式的控制迭代器或索引变量,以便所有的迭代器或索引能协同推进。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值