For-Each循环
For-Each循环也叫增强型的for循环,或者叫foreach循环。
For-Each循环是JDK5.0的新特性(其他新特性比如泛型、自动装箱等)。
For-Each循环的加入简化了集合的遍历。
其语法如下:
for(type element: array)
{
System.out.println(element);
}
例子
其基本使用可以直接看代码:
代码中首先对比了两种for循环;之后实现了用增强for循环遍历二维数组;最后采用三种方式遍历了一个List集合。
import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class ForeachTest { public static void main(String[] args) { int[] arr = {1, 2, 3, 4, 5}; System.out.println("----------旧方式遍历------------"); //旧式方式 for(int i=0; i<arr.length; i++) { System.out.println(arr[i]); } System.out.println("---------新方式遍历-------------"); //新式写法,增强的for循环 for(int element:arr) { System.out.println(element); } System.out.println("---------遍历二维数组-------------"); //遍历二维数组 int[][] arr2 = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}} ; for(int[] row : arr2) { for(int element : row) { System.out.println(element); } } //以三种方式遍历集合List List<String> list = new ArrayList<String>(); list.add("a"); list.add("b"); list.add("c"); System.out.println("----------方式1-----------"); //第一种方式,普通for循环 for(int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); } System.out.println("----------方式2-----------"); //第二种方式,使用迭代器 for(Iterator<String> iter = list.iterator(); iter.hasNext();) { System.out.println(iter.next()); } System.out.println("----------方式3-----------"); //第三种方式,使用增强型的for循环 for(String str: list) { System.out.println(str); } } }
For-Each循环的缺点:丢掉了索引信息。
当遍历集合或数组时,如果需要访问集合或数组的下标,那么最好使用旧式的方式来实现循环或遍历,而不要使用增强的for循环,因为它丢失了下标信息。
满足什么条件才可以使用for-each呢?实现了Iterable接口的对象都可以使用for-each循环。这个简单的接口由单个方法组成,下面就是这个接口的示例额:
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.平行迭代
如果需要并行地遍历多个集合,就需要显式地控制迭代器和数组索引变量,以便所有的迭代器或者索引值变量都可以得到同步前移。
foreach写失效的问题
Java中的细节一定要清楚,否则非常容易出现问题。例如这个场景:遍历一个集合,对符合某种条件的元素做修改。大家往往会写出如下代码:
期待的结果是:
2
2
3
但实际输出为:
1
2
3
这是很容易掉进去的陷阱。即通过foreach遍历对集合元素进行修改。在以为变更已发生的时候,其实变更没有发生。造成数据写入失败。因为
根据oracle的官方文档,正式翻译应该如下
即:foreach里头的的 temp变量只是一个局部变量,而且还是集合中元素的一个副本,并不是元素本身。