Java 中关于Iterator接口

记录一下

1.首先看一下ArrayList类的继承关系图:
ArrayList的继承体系图
Java集合的根接口Collection,继承了Iterable接口。
在这里插入图片描述
Iterable接口包含一个能产生Iterator对象的方法,并且Iterable被foreach用来在序列中移动。因此如果创建了实现Iterable接口的类,都可以将它用于foreach中。使用foreach来遍历集合使得代码更加优雅。
2.Iterator接口中定义了三个方法:
在这里插入图片描述
利用迭代器Iterator遍历集合:

public class IteratorTest {
    public static void main(String[] args) {
        ArrayList<String> strings = new ArrayList<>();

        strings.add("zhangsan1");
        strings.add("zhangsan2");
        strings.add("zhangsan3");

        Iterator<String> iterator = strings.iterator();
        while (iterator.hasNext()) {
            String next = iterator.next();
            System.out.println(next);
        }
    }
}

3.如果使用foreach遍历或者使用迭代器遍历的过程中,对集合结构进行修改(添加或者删除元素),会报错

public class IteratorTest {
    public static void main(String[] args) {
        ArrayList<String> strings = new ArrayList<>();

        strings.add("zhangsan1");
        strings.add("zhangsan2");
        strings.add("zhangsan3");

        // foreach遍历
        for (String string : strings) {
            if (string.equals("zhangsan3")){
                strings.remove("zhangsan3");
            }
        }

        // 迭代器遍历
        Iterator<String> iterator = strings.iterator();
        while (iterator.hasNext()) {
            String next = iterator.next();
            if (next.equals("zhangsan3")){
                strings.remove(next);
            }
        }

        System.out.println(strings);
    }
}

在这里插入图片描述原因分析:以ArrayList为例:
ArrayList中关于Iterator接口的实现:(JDK8在Line846行左右)

private class Itr implements Iterator<E> {
    int cursor;       // index of next element to return
    int lastRet = -1; // index of last element returned; -1 if no such
    // modCount 此列表经过结构修改的次数
    int expectedModCount = modCount;

    Itr() {}

    public boolean hasNext() {
        return cursor != size;
    }

    @SuppressWarnings("unchecked")
    public E next() {
        checkForComodification();
        int i = cursor;
        if (i >= size)
            throw new NoSuchElementException();
        Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length)
            throw new ConcurrentModificationException();
        cursor = i + 1;
        return (E) elementData[lastRet = i];
    }

    public void remove() {
        if (lastRet < 0)
            throw new IllegalStateException();
        checkForComodification();

        try {
            ArrayList.this.remove(lastRet);
            cursor = lastRet;
            lastRet = -1;
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }


final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

ArrayList的remove和add方法调用时,会有一个modCount++操作,记录list被改变的次数.获取集合的Iterator时: int expectedModCount = modCount;两者相等.在迭代的时候,执行add或remove时,modCount会++,而期望中expectedModCount没有改变,两者就不再相等.所以在next()方法里执行checkForComodification()方法就会抛出异常.

在迭代器遍历时,可以通过Iterator对象的remove方法来删除集合中的元素,因为该remove()方法中执行expectedModCount = modCount,同步了两者的值,所以不会再抛异常.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值