• 集合框架遍历方式之——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接口
  • 相关阅读:
    渚漪Day18——JavaWeb 09【JSP】
    渚漪Day17——JavaWeb 08【Session】
    渚漪Day16——JavaWeb 07【Cookie】
    渚漪Day15——JavaWeb 06【HTTPServletRequest】
    渚漪Day14——JavaWeb 05【HTTPServletResponse】
    Typora编写markdown 常用入门
    Vue 笔记
    ABCNN 学习笔记
    DSSM 学习笔记
    支持向量机 SVM 学习笔记
  • 原文地址:https://www.cnblogs.com/FrankLei/p/6238395.html
Copyright © 2020-2023  润新知