Java中for-each循环优先于传统for循环

Java中for-each循环优先于传统for循环
July 11, 2010 | tags Java 通用程序设计 | views 43Comments 0 在jdk1.5以前,我们可以用以下方式遍历集合(迭代器方式):


view sourceprint?1.for(Iterator i = c.iterator(); i.hasNext();) {
2.
doSomething(i.next());
3.}用以下方式遍历数组(索引方式):
view sourceprint?1.for (int i = 0; i < a.length; i++) {
2.
doSomething(a[i]);
3.}迭代器和索引下标变量在循环中出现了三次,这自然就增加了出错的可能性。


从jdk1.5开始Java引入了for-each循环,通过完全地隐藏迭代器和索引变量,避免了混乱和出错的可能。这种模式同时适用于集合和数组:


view sourceprint?1.for(Element e : elements) {
2.
doSomething(e);
3.}利用for-each循环不会有性能损失,实际上,在某些情况下,比起普通的for循环,它还稍有优势,因为它对数组索引的边界值只计算一次(上边那个索引遍历数组的例子中就计算了a.lenght次)。


在对多个集合进行嵌套遍历时,for-each循环的优势更明显。下面的例子是对遍历扑克牌的每张牌(有bug):


view sourceprint?01.//四种花色
02.enum Suit{CLUB,DIAMOND,HEART,SPADE}
03.//13张牌
04.enum Rank{ACE,DEUCE,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE,TEN,JACK,QUEEN,KING}
05.Collection<Suit> suits = Arrays.asList(Suit.values());
06.Collection<Rank> ranks = Arrays.asList(Rank.values());
07....
08.List<Card> cards = new ArrayList<Card>();
09.for (Iterator<Suit> i = suits.iterator(); i.hasNext(); ) {
10.
for(Iterator<Rank> j = ranks.iterator(); j.hasNext(); ) {
11.
cards.add(new Card(i.next(), j.next()));
12.
}
13.}如果你在机器上运行这段程序,会报NoSuchElementException异常,因为调用调用了太多次i.next(),而四次之后已经用完了所有花色,而这时j.next()也只调用了四次,这显然不是我们想要的结果。


当然解决这个bug还是比较简单的,以下是一种ugly的方式:


view sourceprint?1.for (Iterator<Suit> i = suits.iterator(); i.hasNext();) {
2.
Suit suit = i.next();
3.
for (Iterator<Rank> j = ranks.iterator(); j.hasNext();) {
4.
cards.add(new Card(suit, j.next()));
5.
}
6.}

既然上面的方式ugly,那优雅的方式是什么呢,就是今天传说中的for-each循环:


view sourceprint?1.for (Suit suit : suits) {
2.
for (Rank rank : ranks) {
3.
cards.add(new Card(suit, rank));
4.
}
5.}

OK,既然for-each这么优雅,那满足什么条件才可以使用for-each呢?实现了Iterable接口的对象都可以使用for-each循环。这个简单的接口由单个方法组成,下面就是这个接口的示例额:


view sourceprint?1.public interface Iterable<E> {
2.
Iterator<E> iterator();
3.}实现Iterable接口并不难。如果你在变相的类型表示的一组元素,即使你选择不让它实现Collection,也要让它实现Iterable。这样可以允许用户利用for-each循环遍历你的类型,会令用户永远感激不尽的。


总之,for-each循环在简洁性和预防bug方面有着传统的for循环无法比拟的优势,并且没有性能损失,我们应该尽可能地使用for-each循环。不过,遗憾的是在以下三种情况下是不能使用for-each的:


1.过滤
如果要遍历集合,并删除选定的元素,就需要使用显势的迭代器,以便可以调用它的remove方法。


2.转换
如果需要遍历列表或者数组,并取代它部分或者全部的元素值,就需要列表迭代器或者数组索引,以便设定元素的值。


3.平行迭代
如果需要并行地遍历多个集合,就需要显式地控制迭代器和数组索引变量,以便所有的迭代器或者索引值变量都可以得到同步前移。


eg:
List<Case> caseLists = caseService.getDetailYzjByNo(caseBean
.getCaseNo());
for (Case caseinfo : caseLists) {
if (caseinfo.getCaseTypeId() == 134
&& caseBean.getCaseId() != caseinfo.getCaseId()) {
request.setAttribute("LianBanCase", "LianBanCase");
break;
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值