zoukankan      html  css  js  c++  java
  • 集合之二:迭代器

    迭代器的简单使用

      在遍历容器时,我们可以使用for循环或者是增强for循环,但是不同的集合结构在遍历时,我们要针对集合特点采取不同的方式,比如List是链表,我们可以直接当做数组处理,但Map是Key—Value的形式,我们只有获取了键名才能去遍历集合内容。

      很麻烦对吧?

      还好JDK为我们提供了一个接口-------Iterator(迭代器),迭代器为各种容器提供了公共的操作接口。这样使得对容器的遍历操作与其具体的底层实现相隔离,达到解耦的效果。

      查看Iterator的API我们得知,该接口共有3个方法

     

           查看API发现Collection实现了该接口,也就是说Collection的所有子实现类可使用Iterator的方法,同时在Collection中定义了一个方法iterator()

      使用该方法iterator(),要求容器返回一个Iterator对象。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。

      那我们如何使用迭代器呢?

      示例代码如下,关键代码的解释说明已经在注释部分给出,将不再做赘述。

    示例代码:

     1        /**
     2 
     3         * + VX:java8733 获取更多资源
     4 
     5  */
     6 
     7 public class TestIterator {
     8 
     9    
    10 
    11     public static void main(String[] args) {
    12 
    13        List<String> list= new ArrayList();
    14 
    15        list.add("and");
    16 
    17        list.add("try");
    18 
    19        list.add("your");
    20 
    21        list.add("best");
    22 
    23       
    24 
    25        //使用迭代器,对集合Arraylist中的元素进行取出
    26 
    27        //调用集合的方法iterator() 获取Iterator接口的实现类对象()
    28 
    29        Iterator<String> it=list.iterator();
    30 
    31        System.out.println(list.iterator().getClass());//打印的内容是 class java.util.ArrayList$Itr 既是我们的接口的实现类对象
    32 
    33         //接口实现类对象,调用方法hasNext()判断集合中是否有元素
    34 
    35         boolean b = it.hasNext();
    36 
    37         System.out.println(b);
    38 
    39         //接口的实现类对象,调用方法next()取出集合中的元素
    40 
    41         String s = it.next();
    42 
    43         System.out.println("it.next()"+s);
    44 
    45        while(it.hasNext()){
    46 
    47            /*
    48 
    49             * 这里将不会输出"and",因为我们调用一次hasNext,内部的指针就会指向下一个元素
    50 
    51             */
    52 
    53            System.out.println(it.next());
    54 
    55        }
    56 
    57       
    58 
    59     }
    60 
    61    
    62 
    63 }
    64 
    65  

    会遇到的问题(并发修改异常) 

      我们来设想如下的场景: 在list集合迭代元素中,对元素进行判断,一旦条件满足就添加一个新元素。代码如下

     1   /**
     2 
     3         * + VX:java8733 获取更多资源
     4 
     5  */
     6 
     7  
     8 
     9     List<String> list2 = new ArrayList<String>();
    10 
    11        list2.add("abc");
    12 
    13        list2.add("def");
    14 
    15        list2.add("g");
    16 
    17       
    18 
    19        Iterator<String> it=list2.iterator();
    20 
    21        while(it.hasNext()){
    22 
    23            String str=it.next();
    24 
    25            if("g".equals(str)){
    26 
    27               //该操作会导致程序异常: ConcurrentModificationException
    28 
    29               List2.add("b");
    30 
    31            }
    32 
    33        }
    34 
    35        System.out.println(list2);


      这是为什么呢?我们会发现当我们使用迭代器遍历元素的时候, 使用了集合方法修改了集合的长度,这是不允许的。程序抛出异常ConcurrentModificationException,这个异常指的是当方法检测到对象的并发修改,但不允许这种修改时,就会抛出此异常。

          迭代器是依赖于集合而存在的,在判断成功后,集合的中新添加了元素,而迭代器却不知道,所以就报错了,这个错叫并发修改异常。

      那我们应该如何解决呢?

      首先,在迭代时,尽量不要使用集合的方法操作元素。如果要在迭代时对元素操作。我们可以通过ListIterator迭代器来操作元素。

      将上面的代码做如下的修改:

     1  /**
     2 
     3         * + VX:java8733 获取更多资源
     4 
     5  */
     6 
     7  
     8 
     9 ListIterator<String> it=list2.listIterator();
    10 
    11        while(it.hasNext()){
    12 
    13            String str=it.next();
    14 
    15            if("a".equals(str)){
    16 
    17               //子接口ListIterator包含add()方法
    18 
    19               it.add("b");
    20 
    21            }
    22 
    23        }

      

  • 相关阅读:
    SQL Server逻辑读、预读和物理读
    SQL Server 视图
    SQL Server存储机制
    SQLServer
    数据库配置问题整理贴
    分析存储过程重编译的起因以及避免
    存储过程重编译的优点、缺点、确定引发语句
    查询反模式
    查询反模式
    状压DP的总结
  • 原文地址:https://www.cnblogs.com/lotus-wmm/p/8318129.html
Copyright © 2011-2022 走看看