有什么办法可以“ CAST” ArrayList到CopyOnWriteArrayList

nam*_*olk 4 java collections

我知道,当

java.lang.Object
  -> java.util.concurrent.CopyOnWriteArrayList<E>
Run Code Online (Sandbox Code Playgroud)

java.lang.Object 
  -> java.util.AbstractCollection<E>
      -> java.util.AbstractList<E>
          -> java.util.ArrayList<E>
Run Code Online (Sandbox Code Playgroud)

但是我想要的是将的行为添加CopyOnWriteArrayListArrayList

例如:
我想做以下事情。但是tstArry是一个ArrayList。不是CopyOnWriteArrayList

for(TestCls testCls : tstArry)
    if(testCls.getVal1().equals("a1"))
        tstArry.remove(testCls);
Run Code Online (Sandbox Code Playgroud)

还是这是完成工作的唯一方法?

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

tstArry是我没有控件的类中的ArrayList。因此,请把ArrayList的类型更改为另一种是最有效的解决方案。

Pet*_*ček 5

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

澄清EDIT,因为您显然不熟悉迭代器及其功能。从Oracle Collections教程中

An Iterator是使您能够遍历集合并有选择地从集合中删除元素的对象。您可以Iterator通过调用其iterator() 方法来获得集合的。

注意,这Iterator.remove()是在迭代过程中修改集合的唯一安全方法。如果在进行迭代时以任何其他方式修改了基础集合,则行为未指定。

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

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

  • 我认为这里的困惑是,您可以在具有CopyOnWriteArrayList的循环内调用list.remove(),因为它使用快照迭代器。但是,建议使用迭代器(如Slanec所述) (2认同)