Java For-each 的实现原理
来源:互联网 发布:北京和隆优化招聘 编辑:程序博客网 时间:2024/06/03 16:21
参考:
http://blog.csdn.net/a596620989/article/details/6930479
http://stackoverflow.com/questions/85190/how-does-the-java-for-each-loop-work
http://www.leepoint.net/notes-java/flow/loops/foreach.html
以上几篇参考帖子中,这一篇讲的最简洁明了。摘录如下:
For-each Loop
Purpose
The basic for loop was extended in Java 5 to make iteration over arrays and other collections more convenient. This newer for statement is called the enhanced for or for-each (because it is called this in other programming languages). I've also heard it called the for-in loop.
Use it in preference to the standard for loop if applicable (see last section below) because it's much more readable.
Series of values. The for-each loop is used to access each successive value in a collection of values.
Arrays and Collections. It's commonly used to iterate over an array or a Collections class (eg, ArrayList).
Iterable<E>. It can also iterate over anything that implements the Iterable<E> interface (must defineiterator()
method). Many of the Collections classes (eg, ArrayList
) implement Iterable<E>, which makes thefor-each loop very useful. You can also implement Iterable<E> for your own data structures.
General Form
The for-each and equivalent for statements have these forms. The two basic equivalent forms are given, depending one whether it is an array or an Iterable that is being traversed. In both cases an extra variable is required, an index for the array and an iterator for the collection.
【yasi】这里我们只要知道下面的事实就好了:
- For-each语法内部,对collection是用nested iteratoration来实现的,对数组是用下标遍历来实现。
- Java 5 及以上的编译器隐藏了基于iteration和下标遍历的内部实现。(注意,这里说的是“Java编译器”或Java语言对其实现做了隐藏,而不是某段Java代码对其实现做了隐藏,也就是说,我们在任何一段JDK的Java代码中都找不到这里被隐藏的实现。这里的实现,隐藏在了Java 编译器中,我们可能只能像这篇帖子中说的那样,查看一段For-each的Java代码编译成的字节码,从中揣测它到底是怎么实现的了)
下面对“For-each”和“其对等的iteration/index实现”的对比再简洁明了不过了。
for (type var : arr) { body-of-loop}
for (int i = 0; i < arr.length; i++) { type var = arr[i]; body-of-loop}
for (type var : coll) { body-of-loop}
for (Iterator<type> iter = coll.iterator(); iter.hasNext(); ) { type var = iter.next(); body-of-loop}
Example - Adding all elements of an array
Here is a loop written as both a for-each loop and a basic for loop.
double[] ar = {1.2, 3.0, 0.8};int sum = 0;for (double d : ar) { // d gets successively each value in ar. sum += d;}
And here is the same loop using the basic for. It requires an extra iteration variable.
double[] ar = {1.2, 3.0, 0.8};int sum = 0;for (int i = 0; i < ar.length; i++) { // i indexes each element successively. sum += ar[i];}
Where the for-each is appropriate
Altho the enhanced for loop can make code much clearer, it can't be used in some common situations.
使用For-each时对collection或数组中的元素不能做幅值操作
- Only access. Elements can not be assigned to, eg, not to increment each element in a collection.
- Only single structure. It's not possible to traverse two structures at once, eg, to compare two arrays.
- Only single element. Use only for single element access, eg, not to compare successive elements.
- Only forward. It's possible to iterate only forward by single steps.
- At least Java 5. Don't use it if you need compatibility with versions before Java 5.
来自:http://blog.csdn.net/yasi_xi/article/details/25482173
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 For-each 的实现原理
- Java For-each 的实现原理
- 【转】Java 增强的For循环,For each的实现原理
- Java中的for each实现原理与坑
- for each 的实现
- 从字节码看Java中for-each循环(增强for循环)实现原理
- for each 接口的实现
- Java的Iterator和for-each 循环
- java中for each语句的使用
- Java中For-Each循环的使用
- Java 中的for each
- *java*for each
- Java for each语句
- JAVA for each 循环
- java for-each
- java基础for each
- Java for each
- Java for-each循环
- android错误之error loading /system/media/audio/ui/Effect_Tick.ogg
- OC网络工具请求类的封装
- 中文环境的Ubuntu系统加英文环境下的终端
- C#中如何插入照片到Excel
- select与epoll对比
- Java For-each 的实现原理
- 事务的隔离级别
- 运维工具比较
- sendBroadcast与sendStickyBroadcast的区别
- struts 注解配置
- C++虚继承
- Android性能优化-内存泄漏1
- C#通过文件路径获取文件名
- 图片压缩方法