for-each形式的循环

使用数组时,经常会遇到需要从头到尾检查每一个数组元素的情况.例如,为了计算保存在数组中的一些值的总和,或计算平均值,搜索某个值,复制数组等情况,都需要检查每一个数组元素.这种”从头到尾”的操作很常见,所以Java定义了第二种形式的for循环来简化该操作.
这种for语句实现了for-each形式的循环.for-each循环能够以严格的顺序从头到尾遍历对象集合(如数组).近年来,for-each形式的循环在程序语言设计者和程序员中都很流行.Java以前并未提供该功能,不过在JDK5中做为一种增强功能引入了for-each循环,也被称为增强型for循环.
for-each形式的for循环的基本格式如下:
for(type itr-var:collection) statement-block
其中,type指定类型,itr-var指定将要从集合中从头到尾,每次接收一个元素的迭代变量名.collection指定要循环遍历的集合名.有多种可用于for循环的集合类型.在每一次循环迭代时,都要检索集合中的下一个元素并将其保存在itr-var中.循环不断重复,直到获得吉河镇的所有元素为止.因此,当循环遍历长度为N的数组时,增强型for循环按照索引顺序(从0到N-1)获得数组元素.
由于迭代变量从集合获得值,因此type必须与保存在集合中的元素相同或兼容.也就是说,当遍历数组时,type必须与数组的元素类型兼容.
为了理解for-each循环幕后的机理,请考虑他所替换的for循环类型,下面的代码段使用传统的for循环来求和一个数组的值:
        int nums[] = {1,2,3,4,5,6,7,8,9,10};
        int sum = 0;
        
        for(int i=0;i<10;i++) sum += nums[i];
        System.out.println("sum : "+sum);
要求和,需要从头到尾依次读取每一个nums元素,即整个数组以严格的顺序读取.这是通过手动索引由i(循环控制变量)标识的nums数组完成的.而且,必须显式指定循环控制变量的初始值,终值和增量.
for-each形式的for循环可以自动的执行前面的循环,也就是说,不再需要创建循环计数器,指定初始值和终值以及手动索引数组.将自动的遍历整个数组,按顺序从头到尾读取一个元素,例如,下面使用for-each形式的for循环把前面的代码段重写一遍:
        for(int one : nums)
        {
            sum += one;
        }
        System.out.println("sum : "+sum);
问:除了数组之外,还有哪些集合能够提供for-each形式的for循环?
答:for-each循环最重要的用途之一就是遍历由Collections Framework定义的集合的内容:
for-each形式的for循环会从最低索引到最高的索引依次遍历数组的全部元素.虽然for-each循环会一直迭代,直到检查完数组中的全部元素,但是也可以使用break语句提前终止循环,如:
    public static void main(String args[])
    {
        int nums[] = {1,2,3,4,5,6,7,8,9,10};
        int sum = 0;
        for(int one : nums)
        {
            if(sum > 20) break;
            sum += one;
        }
        System.out.println("sum : "+sum);
        
    }
对于for-each形式的for循环有一点要特别注意,他的迭代变量对于内部数组是只读的,给迭代变量赋值对于内部数组无效.换句话说,不能通过赋给迭代变量新值来修改数组的内容.
1.迭代多维数组
增强型for循环也可以用于多维数组.但是要记住,Java中的多维数组是数组的数组,例如,二维数组是一维数组数组的数组,在遍历多维数组时,这一点很重要,因为当迭代一个多维数组时,每一次迭代获得的都是下一级数组,而不是单个元素.而且,for循环的迭代变量必须与获得的数组的类型兼容.例如,对于二维数组,迭代变量必须是一维数组的引用.总之,当使用for-each形式的for循环遍历N维数组时,获得的对象必须是N-1维.为了说明这一点,下面的程序使用嵌套的for循环,按照行顺序,从头到尾获得一个二维数组的元素:
    public static void main(String args[])
    {
        int sum = 0;
        int nums[][] = new int[3][5];
        
        for(int i=0;i<3;i++)
            for(int j=0;j<5;j++) nums[i][j] =  (i+1)*(j+1);
        
        for(int x[] : nums)
        {
            for(int y : x)
            {
                System.out.println("Value is :  "+y);
                sum += y;
            }
        }
        System.out.println("Summation : "+sum);
    }
输出:
Value is : 1
Value is : 2
Value is : 3
Value is : 4
Value is : 5
Value is : 2
Value is : 4
Value is : 6
Value is : 8
Value is : 10
Value is : 3
Value is : 6
Value is : 9
Value is : 12
Value is : 15
Summation : 90
2.应用增强型for循环
由于for-each形式的for循环只能以顺序方式从头到尾遍历数组,因此你可能会认为他的用法受限.其实情况并非如此.很多算法都需要这种机制.最常见的算法之一就是搜索.例如,下面的程序使用for循环在一个无序数组中搜索某个值,找到该值之后就终止.
    public static void main(String args[])
    {
        boolean found = false;
        int nums[] = {3,4,62,3,34,5};
        for(int one : nums)
        {
            if(one == 5) found = true;
        }
        
        if(found) System.out.println("Find :  "+found);
    }
输出:
Find : true
for-each形式的for循环是该情况下的最佳选择,因为搜索无序数组也需要按照顺序检查数组的每一个元素(如果是有序数组可以使用二元搜索,这需要不同的循环形式).其他类型的应用也可以从for-each形式的for循环中获益,包含计算平均值,查找一组值的最大值和最小值,查找重复值等.