首页 > 代码库 > 【代码优化】for-each代替普通的for循环或者while循环

【代码优化】for-each代替普通的for循环或者while循环

对于集合的遍历首选方法是for-each

for(Element e :c){

      doSomething(e);

}

这是1.5版本之后的做法;java1.5之前使用的是Iterator迭代器。


为了弄清楚为啥比普通的for循环或者whlie循环好,请看一下代码

Iterator<Element> i=c.iterator();

while(i.hasNext()){

      doSomething(i.next());

}

Iterator<Element> i2=c.iterator();

while(i.hasNext()){//bug 不应该调用i

      doSomething(i2.next());

}

上面的bug是因为我们经常拷贝相同结构的代码,但是变量使用在作用域类,不会在编译时发现,运行就会出问题。

对于for循环就不会出现这个bug,第一个for循环的变量不能用到同一个方法的第二个for循环中,否则编译出错,

这也看出for循环要强于while循环。


对于多重循环迭代时候,就算是老程序员也容易患一个错误。


例子:用扑克牌例子Card表示牌对象,suit花色,rank点数

Collection<suit>  suits=Arrays.asList(Suit.values);

Collection<rank>  ranks=Arrays.asList(Rank.values);

List<card> cards= new ArrayList<Card>();

for (Iterator<Suit> i=suits.iterator(); i.hasNext()){
      for (Iterator<Rank> j=ranks.iterator(); j.hasNext()){

                   cards.add(new Card(i.next,j.next));//注意
    }

}

发现上面的问题了吗??很多老程序员都会患这种错误,不要说新手了,
 cards.add(new Card(i.next,j.next));

只能得到 j 条数据,而不是我们想要的 i  * j 条数据。


正确的做法是这样的

Collection<suit>  suits=Arrays.asList(Suit.values);

Collection<rank>  ranks=Arrays.asList(Rank.values);

List<card> cards= new ArrayList<Card>();

for (Iterator<Suit> i=suits.iterator(); i.hasNext()){  Suit  suit=i.next();//加上这个,i 的循环不应该放到 j 中做

      for (Iterator<Rank> j=ranks.iterator(); j.hasNext()){

                   cards.add(new Card(suit,j.next));//注意
    }

}


然后对于for-each就不用担心双重,多重迭代了,直接使用多重for-each就可以方便的解决了,也不会出现上面的bug

<pre name="code" class="html"> for(Suit s : suits ){

   for(Rank r: ranks){
      cards.add(s, r);
  }
}


就这么简单,可以看出for-each强于普通的for循环和while循环了吧。


注意:

不过for-each在下列3种情况下不能使用:

  1. 过滤——如果需要迭代集合,并且删除选定元素,就需要使用显示迭代器,才可以调用remove方法
  2. 转换——如果需要遍历列表或者数组,并修改取代列表中的部分元素,就不合适了。
  3. 平行转换——需要并行的遍历多个集合,就需要显示的控制迭代器或者索引变量。