有没有办法将“CAST”ArrayList复制到CopyOnWriteArrayList

时间:2013-06-21 08:43:14

标签: java collections

我知道,

时,施法不是正确的词
java.lang.Object
  -> java.util.concurrent.CopyOnWriteArrayList<E>

java.lang.Object 
  -> java.util.AbstractCollection<E>
      -> java.util.AbstractList<E>
          -> java.util.ArrayList<E>

但我想要的是将CopyOnWriteArrayList的行为添加到ArrayList

例如:
我想做以下。但是tstArry是ArrayList。不是CopyOnWriteArrayList

for(TestCls testCls : tstArry)
    if(testCls.getVal1().equals("a1"))
        tstArry.remove(testCls);

或者这是完成工作的唯一方法吗?

for(int i = 0; i < tstArry.size(); i++)
    if(tstArry.get(i).getVal1().equals("a1"))
        tstArry.remove(i--);

tstArry是一个我没有控制权的类的ArrayList。 所以,请将ArrayList的类型更改为另一个是最大的解决方案。

3 个答案:

答案 0 :(得分:4)

使用增强型remove()循环时,您无法for-each来自迭代集合。 for-each循环隐式使用Iterator<TestCls>JavaDoc明确指出

  

此类iterator()listIterator()返回的迭代器   方法是失败快速:如果列表在结构上被修改了   创建迭代器之后的时间,除了通过之外的任何方式   迭代器自己的remove()add()方法,迭代器将抛出一个   ConcurrentModificationException

for-each循环在内部创建一个迭代器并使用它遍历列表。然后你改变列表的结构......并且迭代器必须失败。问题是您无法访问迭代器方法,因此必须明确使用Iterator<TestCls>。生成的遍历字节码将是相同的,唯一的区别是您可以从列表中删除元素作为遍历它。

for (Iterator<TestCls> iter = tstArry.iterator(); iter.hasNext(); ) {
    TextCls testCls = iter.next();
    if(testCls.getVal1().equals("a1")) {
        iter.remove();
    }
}

澄清编辑,因为您显然不熟悉迭代器及其功能。来自the Oracle tutorial on Collections

  

Iterator是一个允许您遍历a的对象   如果,有选择地收集和从集合中删除元素   期望。您可以通过调用Iterator来获取集合的iterator()   方法

     

请注意,Iterator.remove()是唯一可以安全修改的方法   迭代期间的集合;如果是,则行为未指定   在迭代时,底层集合以任何其他方式进行修改   正在进行中。

     

在需要时使用Iterator代替for-each构造:

     
      
  • 删除当前元素。 for-each构造隐藏了迭代器,因此您无法调用remove()。因此,for-each   构造不可用于过滤。
  •   

答案 1 :(得分:4)

关键是Effective Java,第39项:在需要时制作防御性副本

从其他班级中获取列表。复制一份:

List<TestCls> myCopy = new ArrayList<>(theOtherList);

然后从副本中删除不需要的元素,而不是原始集合。为此,您需要使用Iterator.remove()方法。

或者您使用像Guava这样的库,它允许您使用谓词过滤集合:

Predicate<TestCls> predicate = new Predicate<TestCls>(){
   public boolean apply(TestCls data){
       // add check here
   }
};
List<TestCls> myList = 
    FluentIterable.from(theOtherList).filter(predicate).toList();

答案 2 :(得分:2)

您可以使用迭代器的remove方法来实现此目的:

Iterator<TestCls> i = tstArry.iterator();

while (i.hasNext()) {
    TestCls value = i.next();
    if (value.getVal1().equals("a1"))
        i.remove();
}

但是,应该注意的是,这与具有不同用例的CopyOnWriteArrayList大致正交。