下面分享一个我在写代码时遇到的问题:
import java.util.ArrayList;
import java.util.Iterator;
class Test{
public static void main(String []args) {
ArrayList<String> list1 = new ArrayList<>();
list1.add("a1");
list1.add("a2");
list1.add("a3");
list1.add("a4");
Iterator<String> it=list1.iterator();
while(it.hasNext()) {
if("a3".equals(it.next())){ //在a3后面加入a33
it.add("a33");
}
}
}
}
在console上会出现ConcurrentModificationException异常
接下来分析为什么会出现ConcurrentModificationException异常:
ConcurrentModificationException翻译过来,并发的修改异常。谈到并发,一定是有两个或以上的操作同时进行;谈到修改,一定是有一个行为对上述数组进行增删改查操作。即在it.add("a33");
,it进行add操作,又同时进行遍历操作,数组不知道到底是add还是遍历,才导致了ConcurrentModificationException。
如何解决这个问题?
为了防止对数组同时添加同时遍历所发生的并发修改异常的发生,ListIterator由此而生。
1.ListIterator介绍:
ListIterator接口继承Iterator接口,所以Iterator接口中的方法ListIterator都可以使用,然而ListIterator中特有的方法Iterator无法使用。接下来看一下ListIterator中特有的常用方法:
2.常用方法:
3.ListIterator功能及与Iterator区别:
1.相对Iterator来说,ListIterator它不仅可以向后迭代,它还可以向前迭代。
2.可以在遍历的同时修改 List 的元素
3.可以获取,遍历时游标的索引index
对于ListIterator来说,没有当前元素这一概念,只有游标cursor。游标使的这一迭代器变得功能更强大。
上图为当游标在初始位置时
上图为使用了next()方法,游标往下移;同理,使用previous()方法,游标往前移。
上图为,当游标遍历完所有元素时的位置。
因此,长度为 n 的列表的迭代器有 n+1 个可能的指针位置。
ListIterator相对Iterator增加了如下3个方法:
- boolean hasPrevious():返回该迭代器关联的集合是否还有上一个元素。
- Object previous():返回该迭代器的上一个元素
- void add():在指定位置插入一个元素。
4.解决问题:
回到文章开头的那个问题,我们应用ListIterator之后,问题迎刃而解:
class Test{
public static void main(String []args) {
ArrayList<String> list1 = new ArrayList<>();
list1.add("a1");
list1.add("a2");
list1.add("a3");
list1.add("a4");
ListIterator<String> it=list1.listIterator();
while(it.hasNext()) {
if("a3".equals(it.next())){ //在a3后面加入a33
it.add("a33");
}
}
System.out.println(list1);
}
}
output:
[a1, a2, a3, a33, a4]
还有一个脑洞问题
我们既然可以顺序遍历,那可不可以倒序遍历。
答案是YES!
既然有hasNext(),那就有hasPrevious()