传统for VS 增强for
Java 1.5版本发布之前,首选遍历集合和数组方法:
//遍历集合 List list = new ArrayList<Integer>(); list.add(3); list.add(2); list.add(5); list.add(8); list.add(4); list.add(7); list.add(6); list.add(9); System.out.print("list output: "); for(Iterator i = list.iterator(); i.hasNext();){ System.out.print(i.next() + " "); } //遍历数组 int[] array = {3, 2, 5, 8, 4, 7, 6, 9}; System.out.print("array output: "); for (int i = 0; i < array.length; i++) { System.out.print(array[i] + " "); }
而这种做法并不总是最佳的。因为迭代器和索引变量都会造成一些混乱,与此同时也代表了出错的可能。
迭代器和索引变量在每个循环中出现三次,其中两次很容易出错,一旦出错就无法保证编译器能够发现错误。
Sun 公司Java 开发团队将for-each 循环引入到Java 1.5版本。其主要特点是完全隐藏迭代器或索引变量。
for-each 使用场景有三种:
1> 遍历数组
2> 遍历Collection 下的集合
3> 遍历任何实现Iterable 接口的对象
for-each 无法使用的三种场景:
1> 遍历集合时要删除选定元素
2> 遍历列表或数组时,需要取代它部分或全部的元素值
3> 并行遍历多个集合
for 循环与for-each 循环的关系:语法糖
性能比较:
不会产生性能损失。相反,在实际开发过程中,for-each相较与传统for有时反而会稍有性能优势。因为它对于数组索引只计算一次 ( 虽然这项工作也可手工完成,但程序员不总会这样做 ) 。
对多个集合进行嵌套迭代时,for-each优势更加明显。我们就以纸牌游戏进行举例:
enum Suit { CLUB, DIAMOND, HEART, SPADE, } enum Rank { ACE, DEUCE, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING, } class Card{ public Suit suit; Rank rank; public Card() { } public Card(Suit suit, Rank rank) { this.suit = suit; this.rank = rank; } public Suit getSuit() { return suit; } public Rank getRank() { return rank; } } public class Demo { public static void main(String[] args) { Collection<Suit> suits = Arrays.asList(Suit.values()); Collection<Rank> ranks = Arrays.asList(Rank.values()); List<Card> deck = new ArrayList<Card>(); /* 错误方法 因为在内部循环中调用了太多次suits的next()方法,所以会抛出NoSuchElementException 异常 因将对suits的next() 调用放在外部循环,以便每种花色调用一次 */ // for (Iterator<Suit> i = suits.iterator(); i.hasNext(); ) { // for (Iterator<Rank> j = ranks.iterator(); j.hasNext(); ) { // deck.add(new Card(i.next(), j.next())); // } // } //修改后的方法 // for (Iterator<Suit> i = suits.iterator(); i.hasNext(); ) { // Suit s = i.next(); // for (Iterator<Rank> j = ranks.iterator(); j.hasNext(); ) { // deck.add(new Card(s, j.next())); // } // } //此时for-each的优势就显现出来啦 for (Suit s : suits) { for (Rank r : ranks) { deck.add(new Card(s, r)); } } //输出deck集合 for (Card d : deck) { System.out.println(d.getSuit() + " " + d.getRank()); } } }
总之,for-each 循环在简洁性和预防Bug 方面有着for 循环无法比拟的效果...
参考文献:《Effective Java》