你可能不清楚的Java细节(2)--for及for-each各自循环适用的场景

本文参考资料基于JDK1.8,理论上也适用于之前的版本.

严格的说,for-each是对for的增强,本质上也属于for循环.

forfor-each一般无非也就是如下三种用法,其中第三种也就是我们平时所说的for-each:

//其中list为java.util.List类型

//第一种写法
for (int i=0, n=list.size(); i < n; i++){
	list.get(i);
}

//第二种写法
for (Iterator i=list.iterator(); i.hasNext(); ){
	i.next();
}

//第三种写法:增强型for循环,即for-each    
for(T obj : list){
	//TODO
}

经常在写for循环的时候会很困惑:到底用哪种写法最合适.

一步步来看.

JLS第14.14.2章节 The enhanced for statement中对for-each的有说明,原文太长有兴趣可以点进去自行去看,大体上就是说:

  1. 能使用for-each进行循环的对象,要么是直接或间接的实现了Iterable接口,要么就是个数组.
  2. 如果是数组,那么在执行的时候JVM会解释成如下形式,即第一种写法:
    for (int i=0, n=list.size(); i < n; i++){
    list.get(i);
    }
    //特别要注意,是解释成上面这种写法,而不是下面这样的.毕竟前者的在性能上会更好一些.
    for (int i=0; i < list.size(); i++){
    list.get(i);
    }

3.如果是实现了Iterable接口,那么在执行的时候JVM会解释成如下形式,即第二种写法:

	for (Iterator i=list.iterator(); i.hasNext(); ){
		i.next();
	}

JDKIterable接口的API也指明了该接口是为了让实现类成为for-each语句的目标.

鉴于在执行时JVM会根据对象是数组还是Iterable接口的实现类来自行决定解释成具体哪种形式的写法,因此,虽然for-each有它的局限性,但大部分情况下,我们都可以用for-each替代for,毕竟for-each可以让代码显得更简洁逻辑也更清晰.

但是,还是有例外的情况,那就是既实现了Iterable又实现了RandomAccess的类,比如最常见的ArrayList.

RandomAccessAPI中有指明,实现了RandomAccess接口的类(准确的说,是属于随机访问的List,因为属于随机访问的List应当实现RandomAccess接口),在进行循环时,更适合采用第一种写法(自然也就不适合使用for-each,因为for-each只会判断是不是数组、是不是实现了Iterable接口,并没有对是否实现RandomAccess进行判断).

所以,整个的结论就是:

  1. 如果是数组,则采用第一种或第三种.
  2. 如果是实现了Iterable接口,并且未实现RandomAccess接口(不是随机访问的List),则应当使用第二种或第三种,优先使用第三种即for-each.
  3. 如果是实现了Iterable接口,并且实现了RandomAccess接口(是随机访问的List),则应当使用第一种.

参考资料:

  1. JLS第14.14.2章节 The enhanced for statement
  2. JDK1.8 API
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值