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