在java1.5发行之前,对于集合进行遍历的首选做法如下:
for(Iterator i = c.iterator(); i.hasNext();){ i.next(); }
遍历数组的首先做法是:
for(int i = 0; i < a.length; i++){ a[i]; }
这些做法都比while循环更好,但是他们并不完美。迭代器和索引变量都会造成一些混乱。而且,他们也代表着出错的可能。迭代器和索引变量在每个循环中出现三次,其中有两次让你很容易出错,一旦出错,就无法保证编译器能够发现错误。
java1.5之后引入了for-each循环,通过完全隐藏的迭代器或者索引变量,避免了混乱和出错的可能,这种模式同样使用与集合和数组
for(Element e : elements){ }
当你到冒号 :时,可以把他读作“在.....里面“。因此上面的循环可以读作”对于元素中的每一个元素e"注意,利用for-each循环不会有性能损失,甚至用于数组也是一样,实际上,在某些情况下,比起普通的for循环,他还稍微有些性能优势,因为他对数组索引的边界值只计算一次。虽然可以手工完成这项工作,但是程序员并不总是这么做。
在对多个集合进行嵌套循环迭代时,for-each循环相对于普通的for循环优势会更加明显,下面就是试图对两个集合进行嵌套循环时经常会犯的错误:
enum Suit{CLUB,DIAMOND,HEART,SPADE} 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())); } } public class Card { public Card(Suit next, Rank next2) { System.out.println(next+" " + next2); } }
如果之前没有发现bug也不必难过,许多专家级的程序员偶尔也会犯这样的错误。问题在于,在这个迭代器上对于外部的集合调用了太多次的next方法了,他应该从外部的循环进行调用,以便于每种花色调用一次,但它却是从内部循环调用的,因此他是每张牌调用一次。在用完所有花色之后,循环就会抛出NullPointerException异常。
如果真的那么不幸,并且外部集合的大小是内部集合大小的几倍——可能因为它们是相同的集合——循环就会正常终止,但是不会完成你想要的工作,例如:下面是个考虑不周的尝试,要打印一对骰子的所有 可能的滚动:
enum Face{ONE,TWO,THREE,FOUR,FIVE,SIX} Collection<Face> faces = Arrays.asList(Face.values()); for(Iterator<Face> i = faces.iterator(); i.hasNext();){ for(Iterator<Face> j = faces.iterator(); j.hasNext();){ System.out.println(i.next()+ " " + j.next()); } }
这段程序不会抛出任何异常,而是打印出6对重复的词(从ONE ONE到SIX SIX)而不是预计的36中组合。
为了修正这个bug,必须在外部循环的作用域中添加一个变量来保存外部元素:
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())); } }
如果使用的是嵌套的for-each循环,这个问题就会完全消失。产生的代码就如你所希望得到的那样简洁:
for (Suit suit : suits) { for(Rank rank : ranks){ deck.add(new Card(suit, rank)); } }
for-each循环不仅让你遍历集合和数组,还让你遍历任何实现Iterable接口的对象。这个简单的接口有单个方法组成,与for-each循环同时被添加到java平台,下面就是这个接口的示例:
public interface Iterable<E>{ Iterable<E> iterator(); }
实现Iterable接口并不能,如果你在编写的类型表示的是一组元素,即使你选择不让他实现Collection,也要让它实现Iterable接口,这样可以允许用户利用for-each循环遍历你的类型,会令用户永远感激不尽的。
总之 ,for-each循环在简洁性和放bug方面有着传统for循环无法比拟的优势,并且没有性能损失,应该尽可能的使用for-each循环。遗憾的是,有三种常见的情况布恩无法使用for-each循环:
过滤 ——如果需要遍历集合,并删除选定的元素,就需要使用显示的迭代器,比便于可以调用他的remove方法。
转换——如果需要遍历的列表或者数组,并取代他部分或者全部的元素值,就需要列表迭代器或者数组索引,以便设定元素的值。
平行迭代——如果需要并行的遍历多个集合,就需要显示的控制迭代器或者索引变量,以便所有迭代器或者索引变量都可以得到同步前移。
在以上任何一种情况下,就要使用普通的for循环,要警惕本条目中提到的陷阱,并且要确保做到最好。
相关推荐
下面是用一个传统的for循环遍历集合的例子:用传统的for循环遍历数组的做法如下:这些做法逗比while循环更好,但是它们并不完美。如果真的那么不幸,并且外部集
Effective Java Effective Java Effective Java
程序设计超级经典书籍 Java 编程语言(第三版)---Java 四大名著----James Gosling(Java 之父) Java 编程思想(第2版)----Java 四大名著----Bruce Eckel Java 编程思想(第3版)----Java 四大名著----------------...
The release of Java SE 8 introduced significant enhancements that impact the Core Java technologies and APIs at the heart of the Java platform. Many old Java idioms are no longer required and new ...
Effective java 3 学习记录
这是对Effective-Robotics-Programming-with-ROS这本书的中文学习笔记
《Effective Java》第三版中文版目录 第一章 介绍 1 第二章 创建和销毁对象 4 1 考虑用静态工厂方法替换构造器 4 2 当遇到多个构造器参
effective-java 自己用网上的翻译的html版本,生成的pdf版,仅供参考,仅供参考,仅供参考,仅供参考
effective-java 配套代码
Python is rapidly becoming the standard language for many talks in scientific research, and is particularly popular in biology and bioinformatics. One of the great strengths of Python is the ecosystem...
Effective Java读书笔记.pdf
effective java 读书笔记,第二版自己摘要并翻译,以备速查。
Gosling(Java之父) Java编程思想----Java四大名著----------------Bruce Eckel JAVA 2核心技术 卷I:基础知识)---Java四大名著-----Cay Horstmann JAVA 2核心技术 卷II:高级特性----Java四大名著-----Cay ...
资源里面包含Objective-C 2.0程序设计 原书中文版第2版及代码,还包含Effective Objective-C 2.0英文版完整的电子书
By highlighting the features and comparative elements of each language, and building on the reader's existing knowledge of object-oriented programming, C++ for Java Programmers enables users to ...
html-xhtml-and-css-your-visual-blueprint-for-designing-effective-web-pages
Effective Enterprise Java
Effective Python Development for Biologists: Tools and techniques for building biological programs By 作者: Dr Martin Jones ISBN-10 书号: 153910303X ISBN-13 书号: 9781539103035 出版日期: 2016-09-26 ...
构建高效的Java企业级系统是项困难的工作。本书详细介绍企业级计算技术中的常见问题,并描述使用企业级Java平台技术处理这些问题的方法。... ——John Croupi, Sun著名工程师,《Core J2EEPatterns》作者之一