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;
				}
			}

你可能感兴趣的:(java,设计模式,J#)