for循环的实质及运用

1.1:for (int i = 0; i < args.length; i++) {}基本型式解析

i是一个局部变量,作用域在声明其的for循环中。声明并实例化他是将其用作判断循环终止的条件和作为计数器

1.2: int i = 0;

for ( ;i < args.length;) {
 i++;
}

int i = 0; 声明一个int型的局部变量。
i < args.length;判断循环终止的条件。
i++; 是一个循环的计数器;(也相当于一个游标) 
其实,一,二两种方法的本质是一样的。

2.1: foreach的语句格式:for(元素类型t 元素变量x : 遍历对象obj){引用了x的java语句;} 

2.2:foreach语句是for语句特殊情况下的增强版本,简化了编程,提高了代码的可读性和安全性(不用怕数组越界)。相对老的for语句来说是个很好的补充。提倡能用foreach的地方就不要再用for了。在用到对集合或者数组索引的情况下,foreach显得力不从心,这个时候是用for语句的时候了。foreach一般结合泛型使用.


增强的For循环(foreach)(泛型)在一维数组、二维数组、List中的应用:

示例代码:ForLoop.java


[java]  view plain  copy
 print ?
  1. import java.util.ArrayList;  
  2. import java.util.Iterator;  
  3. import java.util.List;  
  4.   
  5. public class ForLoop {  
  6.   
  7.     public static void main(String[] args) {  
  8.   
  9.         /* 1.普通数组中的使用 */  
  10.         int array[] = { 12345678 };  
  11.   
  12.         // 增强的for循环  
  13.         for (int arritem : array) {  
  14.             System.out.println(arritem);  
  15.         }  
  16.   
  17.         // 普通方法  
  18.         for (int i = 0; i < array.length; i++)  
  19.             System.out.println(array[i]);  
  20.   
  21.         /* 2.二维数组中的使用 */  
  22.         int darray[][] = { { 123 }, { 456, }, { 789 } };  
  23.           
  24.         // 增强的for循环  
  25.         for (int oarr[] : darray) {  
  26.             for (int item : oarr) {  
  27.                 System.out.println(item);  
  28.             }  
  29.         }  
  30.   
  31.         // 普通方法  
  32.         for (int i = 0; i < darray.length; i++) {  
  33.             for (int j = 0; j < darray[i].length; j++) {  
  34.                 System.out.println(darray[i][j]);  
  35.             }  
  36.         }  
  37.   
  38.         /* 3.List中的使用 */  
  39.         List<String> list = new ArrayList<String>();  
  40.         list.add("l1");  
  41.         list.add("l2");  
  42.         list.add("l4");  
  43.         list.add("l4");  
  44.           
  45.         // 增强的for循环  
  46.         for (String item : list){  
  47.             System.out.println(item);             
  48.         }  
  49.                   
  50.         //普通方法  
  51.         for (int i = 0; i < list.size(); i++) {  
  52.             System.out.println(list.get(i));  
  53.         }  
  54.   
  55.         //迭代器遍历  
  56.         for (Iterator<String> it = list.iterator(); it.hasNext();) {  
  57.             System.out.println(it.next());  
  58.         }  
  59.   
  60.            
  61.     }  
  62. }  
在查找和汇总for循环的特性时看到有很多不错的说法,就一起整理过来了,希望有用。

foreach循环中的第一个问题:

考虑下面这段遍历一个用户自定义的aggregator或collection类的代码,这段代码将会打印出什么,抛出异常还是编译器错误:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package test;
 
/**
   * Java Class to show how for-each loop works in Java
   */
public class ForEachTest { 
 
     public static void main(String args[]){
         CustomCollection<String> myCollection = new CustomCollection<String>();
         myCollection.add( "Java" );
         myCollection.add( "Scala" );
         myCollection.add( "Groovy" );
 
         //What does this code will do, print language, throw exception or compile time error
         for (String language: myCollection){
             System.out.println(language);
         }
     }
}

下面是我们的CustomCollection类,这是个参数为泛型的类,与任何其他的Collection类相似,依靠于ArrayList并提供从Collection中添加和删除项的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package test;
 
public class CustomCollection<T>{
     private ArrayList<T> bucket;
 
     public CustomCollection(){
         bucket = new ArrayList();
     }
 
     public int size() {
         return bucket.size();
     }
 
     public boolean isEmpty() {
         return bucket.isEmpty();
     }
 
     public boolean contains(T o) {
         return bucket.contains(o);
     }
 
     public boolean add(T e) {
         return bucket.add(e);
     }
 
     public boolean remove(T o) {
         return bucket.remove(o);
     }  
 
}

答案:

上述代码将无法通过编译,这是因为我们的CustomCollection类没有实现java.lang.Iterable接口,编译期错误如下:

1
2
3
4
5
Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - for -each not applicable to expression type
 
  required: array or java.lang.Iterable
   found:    test .CustomCollection
         at test .ForEachTest.main(ForEachTest.java:24)

从中了解到的一个有趣的事实是:for-each循环仅应用于实现了Iterable接口的Java array和Collection类,而且既然所有内置Collection类都实现了java.util.Collection接口,已经继承了Iterable,这一细节通常会被忽略,这点可以在Collection接口的类型声明“ public interface Collection extends Iterable”中看到。所以为了解决上述问题,你可以选择简单地让CustomCollection实现Collection接口或者继承AbstractCollection,这是默认的通用实现并展示了如何同时使用抽象类和接口以获取更好的灵活性。现在让我们来看看for-each循环的第二个难题:

Java for-each循环的第二个难题:

在下面的代码示例将会抛出ConcurrentModificationException异常。这里我们使用标准iterator和for-each循环遍历ArrayList,随后删除元素,你需要找出哪段代码将会抛出ConcurrentModificationException ,为什么?请注意,答案可能是两个都会,都不会或其中之一。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package test;
 
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
 
/**
   * Java class to demonstrate inner working of for-each loop in Java
   * @author Javin Paul
   **/
public class ForEachTest2 { 
 
     public static void main(String args[]){
         Collection<String> list = new ArrayList<String>();
         list.add( "Android" );
         list.add( "iPhone" );
         list.add( "Windows Mobile" );
 
         // Which Code will throw ConcurrentModificationException, both,
        // none or one of them
 
         // example 1       
         Iterator<String> itr = list.iterator();
         while (itr.hasNext()){
             String lang = itr.next();
             list.remove(lang);
         }
 
          // example 2
         for (String language: list){
             list.remove(language);
         }
     }
}

大约70%的Java开发者都会说第一个代码块会抛出ConcurrentModificationException异常,因为我们没有用iterator的remove方法来删除元素,而是使用ArrayList的 remove()方法。但是,没有多少Java开发者会说出for-each循环也会出现同样的问题,因为我们在这里没有使用iterator。事实上,第二个代码片段也会抛出ConcurrentModificationException异常,这点在解决了第一个困惑之后就变得很明显了。既然for-each循环内部使用了Iterator来遍历Collection,它也调用了Iterator.next(),这会检查(元素的)变化并抛出ConcurrentModificationException。你可以从下面的输出中了解到这点,在注释掉第一个代码段后,当你运行第二个代码段时会得到下面的输出。

1
2
3
4
Exception in thread "main" java.util.ConcurrentModificationException
         at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
         at java.util.AbstractList$Itr.next(AbstractList.java:343)
         at test .ForEachTest2.main(ForEachTest2.java:34)

以上就是关于Java5 for-each循环的全部内容。我们已经看到了Java程序员在编写遍历Collection类的代码时产生的很多问题,特别是在遍历collection的同时删除元素的时候。请牢记,在从任何Collection(例如Map、Set或List)中删除对象时总要使用Iterator的remove方法,也请谨记for-each循环只是标准Iterator代码标准用法之上的一种语法糖(syntactic sugar)而已。

译者注:语法糖(syntactic sugar),也译为糖衣语法,是由英国计算机科学家彼得·约翰·兰达-Peter J. Landin发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会。

原文链接:  javarevisited  翻译:  ImportNew.com  liqing
译文链接:  http://www.importnew.com/11038.html
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值