如果我在方法中声明Iterator,则以下方法有效。如果我在方法之外声明它,它会导致ConcurrentModificationException。我没有任何其他线程运行任何并发操作。我不明白为什么在方法内外声明它之间的区别。我可以在每种方法中声明迭代器,但觉得效率不高。请指出什么是错的。谢谢。
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.Scanner;
public class Linker {
private static LinkedList<String> list = new LinkedList();
public static void main(String[] args){
load("sample.txt");
find("Sam");
}
public static void load(String sourceName){
try {
Scanner in = new Scanner(new File(sourceName));
while (in.hasNextLine()){
String name = in.nextLine();
list.add(new String(name));
}
in.close();
}catch (FileNotFoundException e){
System.out.println("File not found.");
}
}
//static ListIterator<String> iterator = list.listIterator(); //causes ConcurrentModificationException
public static int find(String name){
ListIterator<String> iterator = list.listIterator();//this works
while (iterator.hasNext()){
String x = iterator.next();
}
return -1;
}
}
答案 0 :(得分:2)
在对此方法的两次调用之间修改theDirect
列表时,可能会出现此问题。
当在方法中获得迭代器时,每次调用方法时都将使用“新鲜”迭代器。
当在方法之外获得迭代器时,(在第二次调用期间,在其他人修改了列表之后),它只会注意到“嘿,其他人用这个列表做了些什么,我不能确定我不再处于一致的状态“,并用ConcurrentModificationException
拯救。
答案 1 :(得分:1)
Java中的列表可用于修改计数。也就是说,在让任何人使用ListIterator之前,请在创建时存储modcount。然后在迭代检查时查看创建时的modcount是否大于当前的modcount。
您正在做的是在列表填充之前创建ListIterator,将List的当前modcount设置为0。
private List<String> list = new ArrayList<>();
private ListIterator<String> itr = list.listIterator(); //at this point mod count is 0
public static void load(String sourceName){
list.add("Foo");// increment mod count by 1
}
因此,加载后的任何修改都会将modcount增加1.并且由于modcount在创建ListIterator之前为0,因此任何迭代器调用都将引发一个编码。
另一种解决方案是在加载方法完成添加后创建ListIterator。此时,modcount不会改变。
答案 2 :(得分:0)
应尽快使用迭代器。因此,在方法中创建它是绝对有意义的。
然而,将其创建为实例字段确实没有意义。我假设您在其他方法中添加和删除值。每次执行时,都会修改列表,因此下一次访问迭代器将抛出ConcurrentModificationException
。
答案 3 :(得分:0)
如@ Marco13所示,问题是在调用方法之间修改了theDirect
。大多数馆藏的文档与ArrayList上的文档类似:
此类的迭代器和listIterator返回的迭代器 方法是快速失败的:如果列表在结构上被修改了 创建迭代器之后的时间,除了通过之外的任何方式 迭代器自己删除或添加方法,迭代器会抛出一个 ConcurrentModificationException的。因此,面对并发 修改,迭代器快速而干净地失败,而不是 在不确定的时间冒着任意的,非确定性的行为 在将来。
这意味着一旦创建了迭代器,就不能改变列表本身(除了通过迭代器的方法)。