集合之二:迭代器

迭代器的简单使用

  在遍历容器时,我们可以使用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        }

  

原文地址:https://www.cnblogs.com/lotus-wmm/p/8318129.html