<返回更多

Java中Iterator(迭代器)实现原理

2022-04-20    随心所欲java
加入收藏

JAVA中遍历List时会用到Java提供的Iterator,Iterator十分好用,原因是:

迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。

  Java中的Iterator功能比较简单,并且只能单向移动:

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

  (2) 使用next()获得序列中的下一个元素。

  (3) 使用hasNext()检查序列中是否还有元素。

  (4) 使用remove()将迭代器新返回的元素删除。

只要看看下面这个例子就一清二楚了:

import java.util.*;
public class Muster {
 
     public static void main(String[] args) {
         ArrayList list = new ArrayList();
         list.add( "a" );
         list.add( "b" );
         list.add( "c" );
         Iterator it = list.iterator();
         while (it.hasNext()){
             String str = (String) it.next();
             System.out.println(str);
         }
     }
}

运行结果:

a
b
c

可以看到,Iterator可以不用管底层数据具体是怎样存储的,都能够通过next()遍历整个List。

但是,具体是怎么实现的呢?背后机制究竟如何呢?

这里我们来看看Java里AbstractList实现Iterator的源代码:

?

 public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> { // List接口实现了Collection<E>, Iterable<E>
2 . 
3 .    protected AbstractList() { 
4 .    } 
5 .   
6 .    ... 
7 . 
8 .    public Iterator<E> iterator() { 
9 .    return new Itr();  // 这里返回一个迭代器
10 .    } 
11 . 
12 .    private class Itr implements Iterator<E> {  // 内部类Itr实现迭代器
13 .      
14 .    int cursor = 0 ; 
15 .    int lastRet = - 1 ; 
16 .    int expectedModCount = modCount; 
17 . 
18 .    public boolean hasNext() {  // 实现hasNext方法
19 .            return cursor != size(); 
20 .    } 
21 . 
22 .    public E next() {  // 实现next方法
23 .            checkForComodification(); 
24 .        try { 
25 .        E next = get(cursor); 
26 .        lastRet = cursor++; 
27 .        return next; 
28 .        } catch (IndexOutOfBoundsException e) { 
29 .        checkForComodification(); 
30 .        throw new NoSuchElementException(); 
31 .        } 
32 .    } 
33 . 
34 .    public void remove() {  // 实现remove方法
35 .        if (lastRet == - 1 ) 
36 .        throw new IllegalStateException(); 
37 .            checkForComodification(); 
38 . 
39 .        try { 
40 .        AbstractList. this .remove(lastRet); 
41 .        if (lastRet < cursor) 
42 .            cursor--; 
43 .        lastRet = - 1 ; 
44 .        expectedModCount = modCount; 
45 .        } catch (IndexOutOfBoundsException e) { 
46 .        throw new ConcurrentModificationException(); 
47 .        } 
48 .    } 
49 . 
50 .    final void checkForComodification() { 
51 .        if (modCount != expectedModCount) 
52 .        throw new ConcurrentModificationException(); 
53 .    } 
54 .    } 
55 .}

可以看到,实现next()是通过get(cursor),然后cursor++,通过这样实现遍历。

这部分代码不难看懂,唯一难懂的是remove操作里涉及到的expectedModCount = modCount;

在网上查到说这是集合迭代中的一种“快速失败”机制,这种机制提供迭代过程中集合的安全性。

从源代码里可以看到增删操作都会使modCount++,通过和expectedModCount的对比,迭代器可以快速的知道迭代过程中是否存在list.add()类似的操作,存在的话快速失败!

在第一个例子基础上添加一条语句:

?

import java.util.*;
public class Muster {
 
     public static void main(String[] args) {
         ArrayList list = new ArrayList();
         list.add( "a" );
         list.add( "b" );
         list.add( "c" );
         Iterator it = list.iterator();
         while (it.hasNext()){
             String str = (String) it.next();
             System.out.println(str);
             list.add( "s" );        //添加一个add方法
         }
     }
}

运行结果:

a
Exception in thread "main"
java.util.ConcurrentModificationException
  at java.util.ArrayList$
Itr.checkForComodification(Unknown Source)
  at java.util.ArrayList$Itr.next(Unknown Source)
  at com.hasse.Muster.main(Muster.java:11)

这就会抛出一个下面的异常,迭代终止。

关于modCount,API解释如下:

The number of times this list has been structurally modified. Structural modifications are those that change the size of the list, or otherwise perturb it in such a fashion that iterations in progress may yield incorrect results.

也就是说,modCount记录修改此列表的次数:包括 改变列表的结构,改变列表的大小,打乱列表的顺序等使正在进行迭代产生错误的结果。

Tips:仅仅设置元素的值并不是结构的修改

我们知道的是ArrayList是线程不安全的,如果在使用迭代器的过程中有其他的线程修改了List就会抛出
ConcurrentModificationException,这就是 Fail-Fast机制。

声明:本站部分内容来自互联网,如有版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
▍相关推荐
更多资讯 >>>