目录:情景导入
List集合根据角标存取元素
迭代删除元素并发异常
List集合解决添加元素并发异常
1.情景导入图片出自高新强老师Java网课
我的上一篇知乎大概了解了一下Collection接口的一些基本内容,本次我们关注一下继承了Collection接口的List接口。
我们同样是new一个接口的实现类来探讨。List接口中同样可以使用所有Collection中的方法,并且它也有一些自己的特殊方法。
2.List集合根据角标存取元素存元素
这种根据角标的添加方式是List特有的,Set没有。Set是无序的,根本没有角标这个概念。
List集合的特有方法
注意:这里的角标必须<=size 如果大于size就会在运行时报错
报数组越界IndexOutOfBoundsException取元素
其实和上面操作基本一样,这里顺便给出一个遍历操作
注意:这里不能写<= 否则会越界
3.迭代删除元素并发异常
现在我们简单的用迭代器遍历一下List集合,并将等于2的元素删除
这串代码是不是看起来没什么问题?
——然而他报错了!
这个错叫做‘并发修改异常’
让我们仔细分析一下。首先上个简单的结论:并发修改异常
在迭代集合的过程中,是不允许直接修改集合结构的
本例中我们在迭代过程中删除了集合中的元素 因此报错如何解决这个问题?迭代器给了我们一个用来删除元素的方法remove
我们使用这个方法就不会报错
这个方法不需要填角标,
它会删除当前刚好取出的元素,专业点说就是删除当前正在迭代集合的元素那么具体是咋回事?——分析内部源码
我们进到我们的接口实现类ArrayList里面 找到next()方法
每次在调用next的时候,他都会检查一个啥玩意儿
我们进到这个检查方法里面
这个方法里面有两个常量,一个叫modCount,另一个叫expectedModCountmodCount:集合修改次数
expectedModCount:迭代器中记录的 集合修改的次数
创建迭代器时,会把modCount的值赋给expectedModCount。
一开始这哥俩是相等的,一旦不相等 check方法就会抛出‘并发修改异常’
在本例中,我们一开始add了四个元素,所以modCount的值为4
调用list.iterator();方法时,将modCount的值赋给expectedModCount,
此时他俩相等,it.next()方法可以正常执行
在第一次循环中,我们调用了list.remove()方法,这个方法是list的,不是迭代器给我们的it.remove()。我们此时修改了一次集合,使modCount的值加一变成了5.
在第二次循环执行it,next()方法时,modCount=5,而expectedModCount=4,俩值不相等,因此抛出‘并发修改异常’为什么迭代器自带的remove方法就可以修改呢?其实你仔细一想就能明白,肯定是他内部帮我们顺便修改了expectedModCount呗
我们只需要关心try中的最后一句话 果然就是它又进行了一次赋值 2333
既然执行完remove后 他俩的值又一样了 那么下一次调用it.next自然就不会报异常咯
现在我们已经会迭代删除元素了,接着 我们抛出一个问题:如何迭代增加元素?
这不是一样的嘛?——其实不一样。
因为——迭代器里面就这几个方法,已经被我们用完了,迭代器没有给我们自带添加方法 233
那么 下一个标题 我们就讨论一下这个问题
4.List集合解决添加元素并发异常
我们刚才一直调用的迭代器都是Collection里面的迭代器,
其实List集合也给我们了一个迭代器
我那们进这个listIterator()看看呗
其实就跟 Collection里面的方法差不多 都是给我们返回了一个对象。
Collection里面那个叫Itr,这玩意儿叫ListItr。嗯,这名字没毛病
这玩意儿继承了Itr 并且还额外实现了一个接口ListIterator
这意味着它不但拥有父类Itr里面的全部方法 还拥有自己的一些特有的方法
如果要总结一下有什么特别的方法的话:那就是 ListItr前后都能取值
与next和hasNext相对应 它多了previous和hasPrevious方法
并且 除了remove之外 也多了set设置值 和add添加值 两个方法
那么既然有了add方法 那么要实现3标题末尾提出的问题 就很easy啦