I know that, casting is not the correct word when
java.lang.Object
-> java.util.concurrent.CopyOnWriteArrayList<E>
and
java.lang.Object
-> java.util.AbstractCollection<E>
-> java.util.AbstractList<E>
-> java.util.ArrayList<E>
But what I want is adding the behavior of the CopyOnWriteArrayList
to the ArrayList
.
Eg :
I want to do following. But tstArry is an ArrayList
. not a CopyOnWriteArrayList
for(TestCls testCls : tstArry)
if(testCls.getVal1().equals("a1"))
tstArry.remove(testCls);
Or is this the only way to get the job done?
for(int i = 0; i < tstArry.size(); i++)
if(tstArry.get(i).getVal1().equals("a1"))
tstArry.remove(i--);
tstArry is an ArrayList from a class that I haven't had the control on it. So, Please make the changing the type of ArrayList to another is the far most solution.
You can't remove()
from iterated collection when using the enhanced for-each
loop. The for-each
loop uses Iterator<TestCls>
implicitly. The JavaDoc clearly states that
The iterators returned by this class's
iterator()
andlistIterator()
methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's ownremove()
oradd()
methods, the iterator will throw aConcurrentModificationException
.
The for-each
loop creates an iterator internally and uses it to traverse the list. Then you change the structure of the list ... and the iterator has to fail. The thing is that you don't have access to the iterators methods, so you have to use Iterator<TestCls>
explicitly. The generated traversing bytecode will be the same, the only difference being you being able to remove elements from the list as traverse it.
for (Iterator<TestCls> iter = tstArry.iterator(); iter.hasNext(); ) {
TextCls testCls = iter.next();
if(testCls.getVal1().equals("a1")) {
iter.remove();
}
}
Clarifying EDIT as you are obviously not familiar with iterators and their function. From the Oracle tutorial on Collections:
An
Iterator
is an object that enables you to traverse through a collection and to remove elements from the collection selectively, if desired. You get anIterator
for a collection by calling itsiterator()
method.Note that
Iterator.remove()
is the only safe way to modify a collection during iteration; the behavior is unspecified if the underlying collection is modified in any other way while the iteration is in progress.Use
Iterator
instead of thefor-each
construct when you need to:
- Remove the current element. The
for-each
construct hides the iterator, so you cannot callremove()
. Therefore, thefor-each
construct is not usable for filtering.
The key is Effective Java, Item 39: Make defensive copies when needed
Take the list you get from the other class. Make a copy of it:
List<TestCls> myCopy = new ArrayList<>(theOtherList);
Then remove the unwanted elements from your copy, not the original collection. To do this, you'll need to use the Iterator.remove() method.
Or you use a library like Guava that lets you filter a collection using predicates:
Predicate<TestCls> predicate = new Predicate<TestCls>(){
public boolean apply(TestCls data){
// add check here
}
};
List<TestCls> myList =
FluentIterable.from(theOtherList).filter(predicate).toList();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With