扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
这篇文章将为大家详细讲解有关如何进行Iterator中的Itr类的分析,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。
创新互联建站专注于企业成都全网营销推广、网站重做改版、安丘网站定制设计、自适应品牌网站建设、H5响应式网站、购物商城网站建设、集团公司官网建设、外贸网站制作、高端网站制作、响应式网页设计等建站业务,价格优惠性价比高,为安丘等各大城市提供网站开发制作服务。
好,我们言归正传,来看看他为什么错,错在哪里?
先看代码:
1
哪里错了
很明显,他是在第36行报错的,也就是在遍历完数值为3的数据报错的。让我们往前顺顺,为什么遍历完第二个元素就报错了,因为他遍历完数值为3的数据后,往list里面增加了一个数值为12的数据。
那我们把遍历里面的if判断去掉试试,答案是肯定正确的。那我们找到了原因,也就是在遍历的时候添加了一个元素,所以导致了他错误。
2
错在哪里
我们看一下ArrayList中的源码,他在add方法里面做了什么,导致了他在遍历的时候报错。
图一:
图二:
图三:
图四:
上面的四幅图都是层级调用的关系, 也就是在执行确定按钮的时候,先确定list数组的大小,ensureCapacityInternal方法,如果为空数组,就取ArrayList中的常量DEFAULT_CAPACITY作为容器大小,然后增加修改次数modCount,最后比较最小容量和数组长度的大小,考虑扩容的情况。从刚才的叙述来看,他只是增加修改次数modCount,并考虑是否扩容。
那我们来看一下modCount是什么,以及在哪里使用了,让我们回到这个题目。
在第33行,在list数组上定义了一个iterator,我们跟到源码看一下
也就是他创建了一个Itr类,而这个类包括cursor,lastRet,expectedModCount三个变量,hasNext,next,remove三个方法。
那么我们来科普一下这三个变量分别代表什么意思,cursor表示下一个要访问元素的下标,lastRet表示上一个访问元素的下标,expectedModCount表示期望修改次数。
next方法和remove方法在开始的地方都调用了checkForComodification方法,那该方法里面就是判断modCount和expectedModCount次数是否一样,如果不一样,就抛出异常,很明显,我们开始运行代码时的报错信息与该异常相吻合,那其实我们就知道了他其实是在该处抛出的异常信息导致程序报错,那也就是modCount和expectedModCount是不一样的。
3
断点调试
下面我们从头开始整理一下整个流程,断点调试一下整个代码。
首先他先构造一个数组,并往里面增加了1,3,2数据,在上面已经看过add方法里面有什么,在add方法里面有增加modCount的值,所以在这里modCount已经为3啦。接着定义了一个iterator,刚才我们知道啦其实也就是新建了一个Itr类,那我们看下在33行结束后,iterator的值是什么。
下一个要访问的下标cursor为0,上一个要访问的下标lastRet为-1,预计期望修改次数expectedModCount为3,其实也就是等于他的数组大小size,也就是3。
接着进入35行开始迭代数组,执行hasNext方法,cursor为0,不等于size,为true,继续执行next方法,先判断modCount(也就是3)是否与expectedModCount(也就是3)相等,答案是相等的,再输出该数值1。
接着再进入35行开始迭代数组,执行hasNext方法,cursor为1,不等于size,为true,继续执行next方法,先判断modCount(也就是3)是否与expectedModCount(也就是3)相等,答案是相等的,再输出该数值3。此处注意有if判断。里面有add方法,modCount是要加1的,现在modCount已经变成了4。
接着再进入35行开始迭代数组,执行hasNext方法,cursor为2,不等于size,为true,继续执行next方法,先判断modCount(也就是4)是否与expectedModCount(也就是3)相等,答案是不相等的,抛出异常。
整个流程结束。
ArrayList是不能在遍历的时候,在对其进行修改操作的,包括增加和删除。也就是线程不安全的。如果在遍历的过程中有其他线程修改了lsit,则会抛出异常,这就是fast-fail(快速失败策略),这一策略在源码中的体现就是在next方法的时候,会调用checkForComodification方法,通过比较modCount和expectedModCount两者的是否相等,判断是否在遍历的时候,有进行修改操作,从而确定是否要抛出异常。那么在需要保证数组在遍历的时候不进行修改操作的时候,可以优先使用iterator来遍历。
关于如何进行Iterator中的Itr类的分析就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流