Collision Detection returns ConcurrentModificationException [duplicate] - java

This question already has answers here:
Iterating through a Collection, avoiding ConcurrentModificationException when removing objects in a loop
(31 answers)
Closed 8 years ago.
I'm trying to remove some elements from an ArrayList while iterating it like this:
for (String str : myArrayList) {
if (someCondition) {
myArrayList.remove(str);
}
}
Of course, I get a ConcurrentModificationException when trying to remove items from the list at the same time when iterating myArrayList. Is there some simple solution to solve this problem?

Use an Iterator and call remove():
Iterator<String> iter = myArrayList.iterator();
while (iter.hasNext()) {
String str = iter.next();
if (someCondition)
iter.remove();
}

As an alternative to everyone else's answers I've always done something like this:
List<String> toRemove = new ArrayList<String>();
for (String str : myArrayList) {
if (someCondition) {
toRemove.add(str);
}
}
myArrayList.removeAll(toRemove);
This will avoid you having to deal with the iterator directly, but requires another list. I've always preferred this route for whatever reason.

Java 8 user can do that: list.removeIf(...)
List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c"));
list.removeIf(e -> (someCondition));
It will remove elements in the list, for which someCondition is satisfied

You have to use the iterator's remove() method, which means no enhanced for loop:
for (final Iterator iterator = myArrayList.iterator(); iterator.hasNext(); ) {
iterator.next();
if (someCondition) {
iterator.remove();
}
}

No, no, NO!
In single threated tasks you don't need to use Iterator, moreover, CopyOnWriteArrayList (due to performance hit).
Solution is much simpler: try to use canonical for loop instead of for-each loop.
According to Java copyright owners (some years ago Sun, now Oracle) for-each loop guide, it uses iterator to walk through collection and just hides it to make code looks better. But, unfortunately as we can see, it produced more problems than profits, otherwise this topic would not arise.
For example, this code will lead to java.util.ConcurrentModificationException when entering next iteration on modified ArrayList:
// process collection
for (SomeClass currElement: testList) {
SomeClass founDuplicate = findDuplicates(currElement);
if (founDuplicate != null) {
uniqueTestList.add(founDuplicate);
testList.remove(testList.indexOf(currElement));
}
}
But following code works just fine:
// process collection
for (int i = 0; i < testList.size(); i++) {
SomeClass currElement = testList.get(i);
SomeClass founDuplicate = findDuplicates(currElement);
if (founDuplicate != null) {
uniqueTestList.add(founDuplicate);
testList.remove(testList.indexOf(currElement));
i--; //to avoid skipping of shifted element
}
}
So, try to use indexing approach for iterating over collections and avoid for-each loop, as they are not equivalent!
For-each loop uses some internal iterators, which check collection modification and throw ConcurrentModificationException exception. To confirm this, take a closer look at the printed stack trace when using first example that I've posted:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at TestFail.main(TestFail.java:43)
For multithreading use corresponding multitask approaches (like synchronized keyword).

While other suggested solutions work, If you really want the solution to be made thread safe you should replace ArrayList with CopyOnWriteArrayList
//List<String> s = new ArrayList<>(); //Will throw exception
List<String> s = new CopyOnWriteArrayList<>();
s.add("B");
Iterator<String> it = s.iterator();
s.add("A");
//Below removes only "B" from List
while (it.hasNext()) {
s.remove(it.next());
}
System.out.println(s);

If you want to modify your List during traversal, then you need to use the Iterator. And then you can use iterator.remove() to remove the elements during traversal.

List myArrayList = Collections.synchronizedList(new ArrayList());
//add your elements
myArrayList.add();
myArrayList.add();
myArrayList.add();
synchronized(myArrayList) {
Iterator i = myArrayList.iterator();
while (i.hasNext()){
Object object = i.next();
}
}

One alternative method is convert your List to array, iterate them and remove them directly from the List based on your logic.
List<String> myList = new ArrayList<String>(); // You can use either list or set
myList.add("abc");
myList.add("abcd");
myList.add("abcde");
myList.add("abcdef");
myList.add("abcdefg");
Object[] obj = myList.toArray();
for(Object o:obj) {
if(condition)
myList.remove(o.toString());
}

You can use the iterator remove() function to remove the object from underlying collection object. But in this case you can remove the same object and not any other object from the list.
from here

Related

Two iterators throw ConcurrentModificationException [duplicate]

This question already has answers here:
ConcurrentModificationException using Iterator
(2 answers)
Closed 5 years ago.
I have the following code
public static void main(String[] args) {
List<String> list = new ArrayList<>();
Arrays.stream("hello how are you".split(" ")).forEach(s -> list.add(s));
Iterator<String> it = list.iterator();
ListIterator<String> lit = list.listIterator();
while (it.hasNext()) {
String s = it.next();
if (s.startsWith("a")) {
it.remove();
} else {
System.out.println(s);
}
}
System.out.println(list);
// {here}
while (lit.hasNext()) {
String s = lit.next();
if (s.startsWith("a")) {
lit.set("1111" + s);
} else {
System.out.println(s);
}
}
System.out.println(list);
}
Here, after iterating through the Iterator, I try to iterate through the ListIterator. But the code throws a ConcurrentModificationException. I do the modification using the ListIterator only after the Iterator is done, but why do I get this exception.
When I initalize the ListIterator at {here} instead at the top, the code runs perfectly.
Isn't ConcurrentModificationException thrown when the list is being modified by two threads simultaneously?
Does initializing the iterator, create a lock on the list ? If yes, then why does Java let us to initialize an Iterator after it has already been initialized by another Iterator?
Isn't ConcurrentModificationException thrown when the list is being modified by two threads simultaneously ?
Not necessarily. The ConcurrentModificationException indicates that the list has been structurally changed (except by the Iterator's own remove method) after the Iterator was created. This could be due to multiple threads using the same list, or it could be due to an attempt to for example remove items from an ArrayList inside a for each loop without using an Iterator.
Does initializing the iterator, create a lock on the list ?
No, there are no locks. When the Iterator is created it records the modCount of the ArrayList (a crude representation of the list's state that is incremented on every structural change). If an iterator detects a change to the List's modcount that wasn't caused by its own methods the exception is thrown.
You are getting the exception from the second iterator because of the structural changes made to the list between the second iterator being instantiated and used.
why does Java let us to initialize an Iterator after it has already been initialized by another Iterator?
The ArrayList does not keep track of all the iterators that it has created, or their state. To do so would massively complicate the implementation. The modCount approach is not perfect and is a bit crude, but it is simple and identifies many real bugs.
You have to load the second iterator after you have used the first iterator. Otherwise the second iterator "thinks" the list hasn't been changed but in reality it did. Because the list got changed the second iterator react like "Wait a minute, that shouldn't be here/gone" and throws a ConcurrentModificationException.
It let you initialize the iterator at any time. When you don't change the content you might be even fine with it and you don't get a ConcurrentModificationException because nothing has been changed.
A ConcurrentModificationException may be thrown whenever you try to use an invalid iterator - which can happen whenever you create an iterator and then modify the underlying collection from a different access point. Here, lit is initialized and then the list is modified through it, so its invalidated, which explains the exception.
ListIterator throws ConcurrentModificationException it there is a modification in list after its creation. In your code you have created Iterator and ListIterator at the same time an later you are deleting something from the list which causes ConcurrentModificationException.
To avoid this changes your code to below one. You just need to move the ListIterator initialization after the operations of iterator.
public static void main(String[] args) {
List<String> list = new ArrayList<>();
Arrays.stream("hello how are you".split(" ")).forEach(s -> list.add(s));
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s = it.next();
if (s.startsWith("a")) {
it.remove();
} else {
System.out.println(s);
}
}
System.out.println(list);
ListIterator<String> lit = list.listIterator();
while (lit.hasNext()) {
String s = lit.next();
if (s.startsWith("a")) {
lit.set("1111" + s);
} else {
System.out.println(s);
}
}
System.out.println(list);
}

Java for each loop working

I was working on certain task, when incidentally did something wrong according to me but the code executed and provided correct result. I was little surprised and had question in mind how all these for each loop works.
Example (sample program),
public static void main( String[] args )
{
String myInput = "hello , hi , how are you ";
String[] splitted = myInput.split(",");
List<String> mylist = new ArrayList<String>();
for (String output : splitted)
{
mylist.add(output);
}
for (String output : mylist)
{
System.out.println(output);
mylist = new ArrayList<String>(); //It worked
mylist.add(output);
}
for (String output : splitted)
{
mylist.add(output);
}
for (String output : mylist)
{
System.out.println(output);
mylist.add(output); // After this line it threw exception java.util.ConcurrentModificationException
}
}
I was curious to know and while searching I found one more post that said we can remove elements from list if we used iterator approach, So I tried,
for (String output : splitted)
{
mylist.add(output);
}
for (Iterator iterator2 = mylist.iterator(); iterator2.hasNext();)
{
String string = (String) iterator2.next();
System.out.println(string);
iterator2.remove(); //It worked but if I used the same thing to remove element from original list it threw exception.
}
Now I just want to know what is happening behind the every for each loop quoted above.
I want to know the technical aspect, I know I can not modify the collection in for each loop but in some case stated above it worked why?
Now I just want to know what is happening behind the every for each
loop quoted above
1. for (String output : splitted)
{
mylist.add(output);
}
This adds each output String from splitted array to the mylist list.
2. for (String output : mylist)
{
System.out.println(output);
mylist = new ArrayList<String>(); //It worked
mylist.add(output);
}
The for statement is governed by the following production:
for ( FormalParameter : Expression )
Statement
where Expression must be an instance of java.lang.Iterable, or an array. So this for:each loop is equivalent to this:
Iterator<String> iterator = mylist.iterator();
while (iterator.hasNext()) {
System.out.println(output);
mylist = new ArrayList<String>(); //It worked
mylist.add(output);
}
Here mylist.iterator() will return a new instance of Iterator type:
public Iterator<E> iterator() {
return new Itr();
}
So even if you are creating new ArrayList instances and assigning them to mylist on each iteration, the iterator obtained from the original mylist will still have a reference to the original mylist and will keep iterating through the elements of original mylist. The iterator keeps a reference to the list it was created on. The assignment mylist = new ArrayList<String>() has no effect on the data that the iterator works on because it changes the variable mylist and not the list itself.
3. for (String output : mylist)
{
System.out.println(output);
mylist.add(output); // After this line it threw exception java.util.ConcurrentModificationException
}
Below statement explains this behavior. It is copied from Arraylist doc:
The iterators returned by this class's iterator and listIterator 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 own remove or add methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.
4. for (Iterator iterator2 = mylist.iterator(); iterator2.hasNext();)
{
String string = (String) iterator2.next();
System.out.println(string);
iterator2.remove(); //It worked but if I used the same thing to remove element from original list it threw exception.
}
The above statement also explains the behavior of this for loop: the list can be structurally modified by the iterator's own remove or add methods while iterating through the list.
A for-each loop is possible for Classes that implement Iterable. This also means that you can create Classes yourself which you can use in for-each loops, which can be very comfortable.
This interface forces you to implement a method iterator() which returns an Iterator. Then the for-each loop does nothing but retrieve that iterator and iterate over it using hasNext() and next(). Just the same as you would do it yourself.
The problem with removing is that when you use a for-each loop and then remove an element from the List, the constructed Iterator will not know anything about that change and there will be a ConcurrentModificationException.
But if you call Iterator.remove() directly, the Iterator will know about that change and can handle it.
A common little trick to avoid Iterators and Exceptions at the same time is to do something like this:
List<Object> objects = new ArrayList<Object>();
for (Object object : new ArrayList<Object>(objects)) {
objects.remove(object);
}
So you create a temporary copy of that List, iterate over that, but call remove on the original List.
for-each loop of List will be internally converted to for loop with iterator.
for (String output : mylist)
{
System.out.println(output);
mylist = new ArrayList<String>(); //It worked
mylist.add(output);
}
gets converted to
for (Iterator<String> iterator = mylist.iterator(); iterator.hasNext();) {
String output = (String)iterator.next();
System.out.println(output);
mylist = new ArrayList<String>(); //It worked
mylist.add(output);
}
And since the the snapshot of list is already taken at below
for (Iterator<String> iterator = mylist.iterator(); iterator.hasNext();) {
The loop is running until the last element of list i.e. "how are you".
Whereas, below is not working because of FailFast behaviour of List.
for (String output : mylist)
{
System.out.println(output);
mylist.add(output); // After this line it threw exception java.util.ConcurrentModificationException
}
It says, if you are modifying the list while iterating, with anything other than iterator's own remove method, List will throw ConcurrentModificationException and thats the reason the below is working.
for (Iterator iterator2 = mylist.iterator(); iterator2.hasNext();)
{
String string = (String) iterator2.next();
System.out.println(string);
iterator2.remove(); //It worked but if I used the same thing to remove element from original list it threw exception.
}
That is corrent. You cannot modify value of collection that is beeing iterated over using "foreach" loop, and to do that, you have to use collection's iterator.
It is of course not a problem to add something to a completely different list than the one you are currently traversing, as you did with the line mylist = new ArrayList<String>(); Even though the variable still has the same name, it will point to an entirely different list.
The reason why you cannot add something to a list that is currently being "walked through" is, that the internal implementation of that list might not be able to ensure, that you still get the same order of elements and especially not all remaining elements as you would expect.
This can be understand best if you imagine that you are using a sorted list: you put in a new element, but whether or not you see that element is undefined, as it depends on where you are and what you insert. As Java doesn't know if you are ok with that, it takes the safe road and throws an Exception.
There are however lists that are well capable of being able to be modified during traversal, mostly the concurrent lists in the concurrent package.

Removing items from a list [duplicate]

This question already has answers here:
Getting a ConcurrentModificationException thrown when removing an element from a java.util.List during list iteration? [duplicate]
(11 answers)
Closed 9 years ago.
While looping through a list, I would like to remove an item of a list depending on a condition. See the code below.
This gives me a ConcurrentModification exception.
for (Object a : list) {
if (a.getXXX().equalsIgnoreCase("AAA")) {
logger.info("this is AAA........should be removed from the list ");
list.remove(a);
}
}
How can this be done?
for (Iterator<String> iter = list.listIterator(); iter.hasNext(); ) {
String a = iter.next();
if (...) {
iter.remove();
}
}
Making an additional assumption that the list is of strings.
As already answered, an list.iterator() is needed. The listIterator can do a bit of navigation too.
–---------
Update
As #AyushiJain commented, there is
list.removeIf(...);
You need to use Iterator and call remove() on iterator instead of using for loop.
You cannot do it because you are already looping on it.
Inorder to avoid this situation use Iterator,which guarentees you to remove the element from list safely ...
List<Object> objs;
Iterator<Object> i = objs.iterator();
while (i.hasNext()) {
Object o = i.next();
//some condition
i.remove();
}
You can't and shouldn't modify a list while iterating over it. You can solve this by temporarely saving the objects to remove:
List<Object> toRemove = new ArrayList<Object>();
for(Object a: list){
if(a.getXXX().equalsIgnoreCase("AAA")){
toRemove.add(a);
}
}
list.removeAll(toRemove);
Besides all the excellent solutions offered here I would like to offer a different solution.
I'm not sure if you're free to add dependencies, but if you can, you could add the https://code.google.com/p/guava-libraries/ as a dependency. This library adds support for many basic functional operations to Java and can make working with collections a lot easier and more readable.
In the code I replaced the type of the List by T, since I don't know what your list is typed to.
This problem can with guava be solved like this:
List<T> filteredList = new Arraylist<>(filter(list, not(XXX_EQUAL_TO_AAA)));
And somewhere else you then define XXX_EQUAL_TO_AAA as:
public static final Predicate<T> XXX_EQUAL_TO_AAA = new Predicate<T>() {
#Override
public boolean apply(T input) {
return input.getXXX().equalsIgnoreCase("AAA");
}
}
However, this is probably overkill in your situation. It's just something that becomes increasingly powerful the more you work with collections.
Ohw, also, you need these static imports:
import static com.google.common.base.Predicates.not;
import static com.google.common.collect.Collections2.filter;
//first find out the removed ones
List removedList = new ArrayList();
for(Object a: list){
if(a.getXXX().equalsIgnoreCase("AAA")){
logger.info("this is AAA........should be removed from the list ");
removedList.add(a);
}
}
list.removeAll(removedList);

ConcurrentModificationException In a Java BO

I am getting a java.util.ConcurrentModificationException in this code and can't seem to understand why, or fix it.
In the BO I have this (privileges is an arraylist inside the BO)
public void setPrivilegename(String privilegename) {
this.privileges.add(privilegename);
}
List<PrivilegeObjectBO> arraylist = new ArrayList<PrivilegeObjectBO>();if (rs != null) {
while (rs.next()) {
for (BO bo : arraylist) {
if (bo.getRolepkey()==rs.getInt("ROLE_PKEY")) {
bo.setPrivilegename(rs.getString("SP.NAME"));
}else{
BO newobj = new BO();
newobj.setRolepriviledgepkey(rs.getInt("PRIVILEGE_PKEY"));
newobj.setProticolpkey(protocol);
newobj.setPrivilegename(rs.getString("SP.NAME"));
newobj.setRolepkey(rs.getInt("SRP.ROLE_PKEY"));
arraylist.add(newobj);
}
}
}
}
As per ArrayList javadoc
The iterators returned by this class's iterator and listIterator
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 own remove or add methods, the iterator will throw a
ConcurrentModificationException.
for (BO bo : arraylist)
Above for-each loop gets Iterator for the list and
arraylist.add(newobj);
You are trying to modify the list without using iterators own methods, which results in ConcurrentModificationException
Here is SO discussion on possible solutions.
In java, you will always get a ConcurrentModificationException when you modify the Collection while you are iterating over it.
Possible solution: use a temporary Collection for added or deleted items, and add or delete those items after the iteration is done.
You cannot iterate over ArrayList and add elements to it at the same time with foreach.
Use iterator, like this:
Iterator<PrivilegeObjectBO> iterator = arraylist.iterator();
while (iterator.hasNext()) {
...
}
Others have already pointed out that add-ing to an ArrayList while iterating over it is disallowed.
But to solve your problem anyway, it looks like you need to iterate over the entire list before attempting to add to it, because it your loop appears to be checking to see if anything in the list matches your row to avoid duplicates. In this case you don't want to add to the list while iterating over it because you don't know whether the list has a duplicate until the end.
So just iterate through and check to see if a match is found:
List<PrivilegeObjectBO> arraylist = new ArrayList<PrivilegeObjectBO>();
if (rs != null) {
while (rs.next()) {
boolean found = false;
for (BO bo : arraylist) {
if (bo.getRolepkey() == rs.getInt("ROLE_PKEY")) {
bo.setPrivilegename(rs.getString("SP.NAME"));
found = true;
}
}
if (!found) {
BO newobj = new BO();
newobj.setRolepriviledgepkey(rs.getInt("PRIVILEGE_PKEY"));
newobj.setProticolpkey(protocol);
newobj.setPrivilegename(rs.getString("SP.NAME"));
newobj.setRolepkey(rs.getInt("SRP.ROLE_PKEY"));
arraylist.add(newobj);
}
}
}
Unless you really do want to add a new BO for every non-matching BO already in the list...
Maybe you can take a look at Collections.synchronizedList(List<?>) static method.
It should return a thread safe List from the List object given, and you should not get the exception anymore.
Otherwise, you could try (if applicable) to set the method that accesses to the list synchronized, by adding the keyword synchronized in the method declaration.

Getting a ConcurrentModificationException thrown when removing an element from a java.util.List during list iteration? [duplicate]

This question already has answers here:
Iterating through a Collection, avoiding ConcurrentModificationException when removing objects in a loop
(31 answers)
Closed 5 years ago.
#Test
public void testListCur(){
List<String> li=new ArrayList<String>();
for(int i=0;i<10;i++){
li.add("str"+i);
}
for(String st:li){
if(st.equalsIgnoreCase("str3"))
li.remove("str3");
}
System.out.println(li);
}
When I run this code,I will throw a ConcurrentModificationException.
It looks as though when I remove the specified element from the list, the list does not know its size have been changed.
I'm wondering if this is a common problem with collections and removing elements?
I believe this is the purpose behind the Iterator.remove() method, to be able to remove an element from the collection while iterating.
For example:
Iterator<String> iter = li.iterator();
while(iter.hasNext()){
if(iter.next().equalsIgnoreCase("str3"))
iter.remove();
}
The Java 8 way to remove it from the List without Iterator is:
li.removeIf(<predicate>)
i.e.
List<String> li = new ArrayList<String>();
// ...
li.removeIf(st -> !st.equalsIgnoreCase("str3"));
Note that this exception does not always indicate that an object has been concurrently modified by a different thread. If a single thread issues a sequence of method invocations that violates the contract of an object, the object may throw this exception. For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will thow this exception
Taken from http://download.oracle.com/javase/1.4.2/docs/api/java/util/ConcurrentModificationException.html
yes people run into it -- the problem is you can't modify the list while iterating over it. I have used 2 alternatives in the past:
You can keep track of the indexes of the items you want to remove, and then remove them after you are done iterating.
Or you can copy all the ones you want to keep into a new list as you iterate, and then discard the old list when done.
those options assume you have to iterate over the list to find the elements to remove -- useful in cases where the list elements are complex objects with properties you might test on.
In your particular case, you dont even need to iterate, as you can just use removeAll. Look at the API here. There are also nifty methods like retainAll that discard everything that is not in the argument. You can use remove/retain-like methods whenever the objects in the list implement equals and hashcode properly. If you cannot rely on equals/hashcode to identify equality between instances in your app, you will have to do the removal yourself....
Try this (Java 8):
list.removeIf(condition);
You could make a copy of list you want to remove element from, directly in for-each loop. For me, that is the simpliest way. Something like this:
for (String stringIter : new ArrayList<String>(myList)) {
myList.remove(itemToRemove);
}
Hope that will help you..
I think it is worth mentioning the Java 8 version
#Test
public void testListCur() {
List<String> li = new ArrayList<String>();
for (int i = 0; i < 10; i++) {
li.add("str" + i);
}
li = li.stream().filter(st -> !st.equalsIgnoreCase("str3")).collect(Collectors.toList());
System.out.println(li);
}
ArrayList has field modCount - count of collection modifications
When you invoke method iterator() creates new object Itr. It has field expectedModCount. expectedModCount field initialize by modCount value. When you invoke
li.remove("str3");
modCount increments. When do you try access to li via iterator
checks that expectedModCount == modCount
and if it is false throws ConcurrentModificationException
Hence if you get iterator and after collection modified - iterator is considered not valid and you cannot use it.
I think that best answer is from bigdev.de, but i would like to add something to it(like if the item is removed from a list, maybe you would like to log that somewhere or something):
List<String> list = new ArrayList<>();
list.removeIf(a -> {
boolean condition = a.equalsIgnoreCase("some condition");
if(condition)
logger.info("Item removed from the list: " + a);
return condition;
});
I got this problem and I think the easier way is the same with the second way that hvgotcodes gave.
Or you can copy all the ones you want to keep into a new list as you iterate, and then discard the old list when done.
#Test
public void testListCur(){
List<String> li=new ArrayList<String>();
for(int i=0;i<10;i++){
li.add("str"+i);
}
List<String> finalLi = new ArrayList<String>();
for(String st:li){
if(st.equalsIgnoreCase("str3")){
// Do nothing
} else {
finalLi.add(st);
}
}
System.out.println(finalLi);
}
I looped a different way...
public void testListCur(){
List<String> li=new ArrayList<String>();
for(int i=0;i<10;i++){
li.add("str"+i);
}
for(int i=0; i<li.size(); i++)
if(li.get(i).equalsIgnoreCase("str3"))
li.remove(i--);
System.out.println(li);
}

Categories

Resources