集合框架遍历方式之——for-each循环

从Java5起,在Java中有了for-each循环,可以用来循环遍历collection和array。Foreach循环允许你在无需保持传统for循环中的索引,或在使用iterator /ListIterator(ArrayList中的一种迭代器实现)时无需调用while循环中的hasNext()方法就能遍历collection。for-each循环简化了任何Collection或array的遍历过程。但是使用foreach循环也有两点需要注意。

  1. 使用foreach循环的对象,必须实现了Iterable<T>接口

请看如下示例:

 1 import java.util.ArrayList;
 2 
 3 public class ForeachTest1 {
 4 
 5     public static void main(String args[]) {
 6         CustomCollection<String> myCollection = new CustomCollection<String>();
 7         myCollection.add("Java");
 8         myCollection.add("Scala");
 9         myCollection.add("Groovy");
10 
11         // What does this code will do, print language, throw exception or
12         // compile time error
13         for (String language : myCollection) {
14             System.out.println(language);
15         }
16     }
17 
18     private class CustomCollection<T> {
19         private ArrayList<T> bucket;
20 
21         public CustomCollection() {
22             bucket = new ArrayList();
23         }
24 
25         public int size() {
26             return bucket.size();
27         }
28 
29         public boolean isEmpty() {
30             return bucket.isEmpty();
31         }
32 
33         public boolean contains(T o) {
34             return bucket.contains(o);
35         }
36 
37         public boolean add(T e) {
38             return bucket.add(e);
39         }
40 
41         public boolean remove(T o) {
42             return bucket.remove(o);
43         }
44 
45     }
46 }

上述代码将无法通过编译,这是因为代码中的CustomCollection类没有实现Iterable<T>接口,编译期的报错如下:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
    Can only iterate over an array or an instance of java.lang.Iterable

    at Text.ForeachTest1.main(ForeachTest1.java:15)

事实上,无需等到编译时才发现报错,eclipse会在这段代码写完之后就会在foreach循环处显示错误:Can only iterate over an array or an instance of java.lang.Iterable

从上述示例可以再次得到确认的是,foreach循环只适用于实现了Iterable<T>接口的对象。由于所有内置Collection类都实现了java.util.Collection接口,已经继承了Iterable,所以为了解决上述问题,可以选择简单地让CustomCollection实现Collection接口或者继承AbstractCollection。解决方式如下:

 1 import java.util.AbstractCollection;
 2 import java.util.ArrayList;
 3 import java.util.Iterator;
 4 
 5 public class ForeachTest {
 6     public static void main(String args[]) {
 7         CustomCollection<String> myCollection = new CustomCollection<String>();
 8         myCollection.add("Java");
 9         myCollection.add("Scala");
10         myCollection.add("Groovy");
11         for (String language : myCollection) {
12             System.out.println(language);
13         }
14     }
15 
16     private static class CustomCollection<T> extends AbstractCollection<T> {
17         private ArrayList<T> bucket;
18 
19         public CustomCollection() {
20             bucket = new ArrayList();
21         }
22 
23         public int size() {
24             return bucket.size();
25         }
26 
27         public boolean isEmpty() {
28             return bucket.isEmpty();
29         }
30 
31         public boolean contains(Object o) {
32             return bucket.contains(o);
33         }
34 
35         public boolean add(T e) {
36             return bucket.add(e);
37         }
38 
39         public boolean remove(Object o) {
40             return bucket.remove(o);
41         }
42 
43         @Override
44         public Iterator<T> iterator() {
45             // TODO Auto-generated method stub
46             return bucket.iterator();
47         }
48     }
49 }

2.foreach循环的内部实现也是依靠Iterator进行实现的

为了验证foreach循环是使用Iterator作为内部实现这一事实,我们依然采用本文最开始的实例进行验证:

 1 public class ItaratorTest {
 2 
 3     public static void main(String[] args) {
 4         Collection<String> list = new ArrayList<String>();
 5         list.add("Android");
 6         list.add("IOS");
 7         list.add("Windows Mobile");
 8 
 9         // example1
10         // Iterator<String> iterator = list.iterator();
11         // while (iterator.hasNext()) {
12         // String lang = iterator.next();
13         // list.remove(lang);
14         // }
15 
16         // example 2
17         for (String language : list) {
18             list.remove(language);
19         }
20     }
21 
22 }

程序运行时所报异常:

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
    at java.util.ArrayList$Itr.next(ArrayList.java:831)
    at Text.ItaratorTest.main(ItaratorTest.java:22)

此异常正说明了for-each循环内部使用了Iterator来遍历Collection,它也调用了Iterator.next(),这会检查(元素的)变化并抛出ConcurrentModificationException。

总结:

  • foreach循环通过iterator实现,使用foreach循环的对象必须实现Iterable接口
原文地址:https://www.cnblogs.com/FrankLei/p/6238395.html