博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
迭代器
阅读量:6884 次
发布时间:2019-06-27

本文共 2687 字,大约阅读时间需要 8 分钟。

hot3.png

public static void main(String[] args) {    List
 list = new ArrayList
();    list.add("A");    list.add("B");    list.add("C");    Iterator
 iterator = list.iterator();    while(iterator.hasNext()) {//      list.remove("C");        System.out.println(iterator.next());    }}

以上代码运行都没有问题,就是取出List数据,然后打印。

但是要是把注释打开那就会报错,java.util.ConcurrentModificationException,这里是为什么呢?那就来讨论一下迭代器的原理吧。

145403_I12B_1269959.png

通过list.iterator查找发现上面截图,里面创建了Itr对象,下面就看看这个对象的具体内容。

private class Itr implements Iterator
 {    int cursor = 0;    int lastRet = -1;    int expectedModCount = modCount;    public boolean hasNext() {        return cursor != size();    }    public E next() {        checkForComodification();        try {            E next = get(cursor);            lastRet = cursor++;            return next;        } catch (IndexOutOfBoundsException e) {            checkForComodification();            throw new NoSuchElementException();        }    }    public void remove() {        if (lastRet == -1)            throw new IllegalStateException();        checkForComodification();        try {            AbstractList.this.remove(lastRet);            if (lastRet < cursor)                cursor--;            lastRet = -1;            expectedModCount = modCount;        } catch (IndexOutOfBoundsException e) {            throw new ConcurrentModificationException();        }    }    final void checkForComodification() {        if (modCount != expectedModCount)            throw new ConcurrentModificationException();    }}

Itr是AbstractList的一个内部类。

方法hasNext:比对cursor(下一个要访问的元素的索引)与当前长度。

方法next:根据cursor值获取元素信息。

方法remove:删除lastRet(上一个访问元素的索引)值获取元素信息。

方法checkForComodification:检验(expectedModCount与modCount是否相等),前面的错误就是这里产生的。

public boolean remove(Object o) {    if (o == null) {        for (int index = 0; index < size; index++)        if (elementData[index] == null) {            fastRemove(index);            return true;        }    } else {        for (int index = 0; index < size; index++)        if (o.equals(elementData[index])) {            fastRemove(index);            return true;        }    }    return false;}private void fastRemove(int index) {    modCount++;    int numMoved = size - index - 1;    if (numMoved > 0)        System.arraycopy(elementData, index+1, elementData, index, numMoved);    elementData[--size] = null; // Let gc do its work}

ArrayList的方法remove只是修改了参数modCount。

也就是在使用迭代器遍历的时候,就不能使用List自身的方法(add/remove)去修改原来的List的结构,要不会报错,而使用迭代器自身的方法(remove)是不会报错的,这又是为什么呢?

152758_aiQz_1269959.png

上图中的红框中明显发现,是把下一个访问的元素下标及上一个访问元素下标给修改了。

总结

JAVA的迭代器更像是数据库中的一个镜像,当你使用原始List修改了原始数据结构时,它会报错,必须使用迭代器的方法remove才可以不会报错。

转载于:https://my.oschina.net/u/1269959/blog/529602

你可能感兴趣的文章
提升机器学习数学基础,这7本书一定要读-附pdf资源
查看>>
25G与100G以太网光模块解决方案
查看>>
社交网络犯罪金额超30亿
查看>>
ngx_lua_module开发(2012-11-16 23:46)
查看>>
如何用Java实现.NET中DataTable功能
查看>>
【13】线程间的信号处理
查看>>
linux yum软件包管理器
查看>>
Linux学习笔记<二十九>——http服务
查看>>
VMware虚拟机克隆CentOS6.4网卡无法正常启动解决案例
查看>>
龙芯pmon初探
查看>>
MongoDB和pymongo入门
查看>>
Service IP 原理 - 每天5分钟玩转 Docker 容器技术(137)
查看>>
手写数字识别系统之数字提取
查看>>
位运算符 209
查看>>
python之列表使用方法总结
查看>>
6.代理模式
查看>>
Linux下安装Hadoop(2.7.1)详解及WordCount运行
查看>>
MSSQL 2005降低权限运行的方法
查看>>
OpenCV3与深度学习实例-使用GoogLeNet模型进行图片分类识别
查看>>
8月第2周国内IT类网站/频道:太平洋降至第二
查看>>