2013-07-26 57 views
0

我有下面的示例java泛型代码,我根据StackOverflow上的人的建议进行了修改。编译正在进行。java泛型运行时error.java.util.ConcurrentModificationException

import java.util.*; 

public class GenericBox<T> 
{ 

     private List<T> tList; 
     private Iterator<T> itor; 

     public GenericBox() 
     { 
       tList = new ArrayList<T>(); 
       itor = tList.listIterator(); 
     } 

     public void insert(T element) 
     { 
       tList.add(element); 
     } 

     public T retrieve() 
     { 
       if(itor.hasNext()) 
       { 
         return itor.next(); 
       } 
       return null; 
     } 

     public static void main (String [] args) 
     { 

       GenericBox <String> strbox = new GenericBox<String>(); 
       GenericBox <String> intbox = new GenericBox<String>(); 

       strbox.insert(new String("karthik")); 
       strbox.insert(new String("kanchana")); 
       strbox.insert(new String("aditya")); 


       String s = strbox.retrieve(); 
       System.out.println(s); 

       s = strbox.retrieve(); 
       System.out.println(s); 

       s = strbox.retrieve(); 
       System.out.println(s); 
     } 
} 

我收到以下运行时错误。

Exception in thread "main" java.util.ConcurrentModificationException 
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:819) 
    at java.util.ArrayList$Itr.next(ArrayList.java:791) 
    at GenericBox.retrieve(GenericBox.java:24) 
    at GenericBox.main(GenericBox.java:40) 

回答

5

这有什么好做仿制药,并一切做,你直接修改(以insert)集合,然后试图用其插入之前创建一个迭代的事实。不要这样做。

ArrayList文档:

此类的iterator和listIterator方法返回的迭代器是快速失败的:如果列表随时结构上修改后的迭代器创建的,以任何方式,除了通过迭代器自己的remove或add方法,迭代器将抛出一个ConcurrentModificationException异常。因此,面对并发修改,迭代器快速而干净地失败,而不是在将来某个未确定的时间冒着任意的,非确定性的行为风险。

如果必须保持迭代器周围,使用增加,而不是一个新值:

private ListIterator<T> itor; // Not just Iterator<T>; you need the add method 

public void insert(T element) 
{ 
    itor.add(element); 
} 

这将是最好不要让迭代器周围虽然 - 这是非常很少有人使用迭代器而不是直接循环。

1

你会得到这个异常,因为列表已经在创建迭代器和它的用法之间被修改了。当您实际想要迭代列表时,您应该仅调用iterator()。之前没有。而且你不应该将迭代器存储在实例字段中。只在局部变量中。

+0

你是说迭代器不应该是一个实例变量。每一个方法应该创建一个自己的构造函数的副本?这是一种被接受/推荐的编码习惯吗? – liv2hak

+1

迭代器只能使用一次。在使用时您无法修改集合。当你想迭代时,你需要一个新的迭代器到集合中,这很简单。大多数情况下,你甚至不需要迭代器:for-each循环会为你创建一个:'for(T element:tList)...' –