是否可以执行以下操作?
List<String> list = new ArrayList<String>();
Iterator<String> iterator = list.listIterator();
populateList(list);
我在使用数据填充列表之前创建一个列表并获取其迭代器。我能使用迭代器获取列表的元素吗?获取迭代器和填充数组的顺序是否会有所不同?
任何帮助将不胜感激。
答案 0 :(得分:6)
是的,这很重要。当您在迭代器上使用hasNext()
或next()
时,您将获得ConcurrentModificationException。 ArrayList
的迭代器是快速失败的,这意味着只要通过添加或删除元素,arraylist的基础结构发生变化,它就会抛出CME。
修改强> 迭代器首先在hasNext()和next()
中调用checkForComodification()
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
答案 1 :(得分:1)
Java在其数据结构上使用时间戳。在执行next()
或hasNext()
方法之前,它将检查时间戳是否等于创建迭代器时的时间戳。
原因是例如在HashSet<T>
的情况下,可以定义迭代器,但在添加元素之后,订单不能保证是相同的。因此,活动迭代器可以多次生成一些项目,而其他项目根本不会迭代。
答案 2 :(得分:0)
有关Java中Iterator的重要观点:
1)Java支持泛型中的迭代器所以总是使用Iterator的通用版本,而不是使用Iterator和原始类型。
2)如果你想从Collection中删除对象,而不是使用for-each循环,而是使用Iterator的remove()方法来避免任何ConcurrentModificationException
。
3)如果在迭代开始后修改了Collection,则使用Iterator迭代收集将受ConcurrentModificationException
的限制,但这只发生在故障快速迭代器中。
4)Java中有两种类型的迭代器,即故障快速和故障安全。
示例: -
List<String> li = new ArrayList<String>();
li.add("list1");
li.add("list2");
li.add("list3");
System.out.println("Added");
for(String st:li){
if(st.equalsIgnoreCase("list1"))
li.remove("list1");
}
在这种情况下,您将获得ConcurrentModificationException
。所以修改for循环使它工作。
Iterator<String> iter = li.iterator();
while(iter.hasNext()){
if(iter.next().equalsIgnoreCase("list1"))
iter.remove();
}
了解详情:http://javarevisited.blogspot.com/2011/10/java-iterator-tutorial-example-list.html#ixzz2eSRG7gAT