I get an ConcurrentModificationException error in following situation. The line
where this occurs is marked with "<-------- ConcurrentModificationException"
I have a main thread which reads from a list as follow:
List<ThemeCacheIndex> list = Collections.synchronizedList(themeCacheList);
synchronized (list) {
Iterator<ThemeCacheIndex> it = list.iterator();
while (it.hasNext()) {
ThemeCacheIndex themeCacheIndex = it.next(); <-------- ConcurrentModificationException
doSomething();
}
}
I have a AsyncTask which deletes from this list:
#Override
protected String doInBackground(String... params) {
someElementsToRemove = calculateWhichElementsToRemove();
for(int i=0 ; i < someElementsToRemove.size() ; i++){
themeCacheList.remove(someElementsToRemove.get(i));
}
}
I can imagine, that it comes to a concurrent situation, but I thought to prevent this with a synchronized list on the main thread.
It seems I did not understood the concept of multithreading and shared objects.
Can someone help me out of this problem ? How can I prevent this conflict ?
Quoting Collections Javadoc:
Returns a synchronized (thread-safe) list backed by the specified
list. In order to guarantee serial access, it is critical that all
access to the backing list is accomplished through the returned list.
If your AsyncTask modifies the themeCacheList, the synchronization as you did it won't help, as a backing list is modified.
The AsyncTask code is fine. Do this for the "main" thread code:
synchronized (themeCacheList) {
Iterator<ThemeCacheIndex> it = themeCacheList.iterator();
while (it.hasNext()) {
ThemeCacheIndex themeCacheIndex = it.next();
doSomething();
}
}
As you can see I've removed Collections.synchronizedList because it is redundant and I'm synchronizing directly on themeCacheList.
Not sure I have a good solution, but I guess these 2 examples shows the problem and a possible solution.
The "Possible duplicate" Answers do not show any solution, but just explaining what is the problem.
#Test
public void testFails(){
List<String> arr = new ArrayList<String>();
arr.add("I");
arr.add("hate");
arr.add("the");
arr.add("ConcurrentModificationException !");
Iterator i = arr.iterator();
arr.remove(2);
while(i.hasNext()){
System.out.println(i.next());
}
}
#Test
public void testWorks(){
List<String> arr = new CopyOnWriteArrayList<>();
arr.add("I");
arr.add("hate");
arr.add("the");
arr.add("ConcurrentModificationException !");
Iterator i = arr.iterator();
arr.remove(2);
while(i.hasNext()){
System.out.println(i.next());
}
}
Related
So this question is a little bit different from the others i've found on here about concurrent exception when modifying the list- because this happens when im modifying an internal list of an object within the list. This is the only method accessing the internal list
Here's where i call the method
public void interactWithItem(int targetIDX, int targetIDY){
for(Iterator<Item> it = listOfAllItems.iterator(); it.hasNext();){
Item tempItem = it.next();
//Maybe i should refine more, in world, so forth
if(tempItem.tilePosX == targetIDX && tempItem.tilePosY == targetIDY){
if(tempItem.name.equals("chest")){
System.out.println("Interacting with Chest!");
if(!tempItem.containedItems.isEmpty()){
for(Iterator<Item> tempIt = tempItem.containedItems.iterator(); tempIt.hasNext();){
Item tItem = tempIt.next();
System.out.println("Chest contains "+tItem.name+" "+tItem.amount);
Character.c.addItem("player", tItem.name, tItem.amount);
removeContainedItem("chest", tItem.name);
}
}else{
System.out.println("Chest is empty");
}
}
}
}
}
Here's the method that causes the issue, if i comment out the i.remove(); the issue seizes to happen- so its only upon removal, yet no other method or class is accessing the internal list ?
public void removeContainedItem(String containerName, String itemName){
System.out.println("Removing "+itemName+" in "+containerName);
for(Iterator<Item> it = listOfAllItems.iterator(); it.hasNext();){
Item tItem = it.next();
if(tItem.name.equals(containerName)){
for(Iterator<Item> i = tItem.containedItems.iterator(); i.hasNext();){
Item tempItem = i.next();
System.out.println(tempItem.name);
if(tempItem.name.equals(itemName)){
i.remove();
}
}
}
}
}
Thanks for all the help! Hope someone can clarify and give me instructions as to how i might go about fixing this thing? Im a bit at a loss.
Concurrent Modification Exception occurs when a collection is modified between the iterations. We can use ConcurrentHashMap or CopyOnWriteArrayList to overcome this issue.
If hitting UnsupportedOperationException, change the ArrayList to LinkedList
Might be :
**Item tItem = tempIt.next();**
When you create an item you then add it to more than one list. And when one of them tries to modify it you can get exceptions. Because bouth lists are using the same item, exactly the same one.
Fix that might help would be :
Item newItem = new Item();
newItem = tempIt.next();
Simply create new item for each list and modify them as you please.
Or create a new list for :
public void removeContainedItem(String containerName, String itemName){
And modify new copy list with items, then set previous list to modified one.
This is a follow up to my previous question :
Collection - Iterator.remove() vs Collection.remove()
The below two pieces of code , which apparently differs only by a single line , but one throws exception and other don't . Can you please explain the difference ?
List<String> list = new ArrayList<String>
(Arrays.asList("noob1","noob2","noob3"));
System.out.println(list);
for (String str : list) {
if (str.equals("noob2")) {
list.remove(str);
}
}
runs fine , but if i change the condition to
if (!str.equals("noob2"))
the code throws exception !
What happens in this situation is you are removing the second list element.
List<String> list = new ArrayList<String>
(Arrays.asList("noob1", "noob2", "noob3", "noob4"));
System.out.println(list);
for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {
String str = iterator.next();
if (str.equals("noob3")) {
System.out.println("Checking "+str);
list.remove(str);
}
}
System.out.println(list);
prints
[noob1, noob2, noob3, noob4]
Checking noob1
Checking noob2
Checking noob3
[noob1, noob2, noob4]
By removing the second last element you have reduced the size to the number of elements which you have iterated over.
// from ArrayList.Itr
public boolean hasNext() {
return cursor != size;
}
This causes the loop to exit early before the concurrent modifcation check is performed in next(). If you remove any other element next() is called and you get a CME.
BTW Something which also bypasses the check is
for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {
String str = iterator.next();
System.out.println("Checking "+str);
if (str.equals("noob2")) {
list.remove("noob1");
list.remove("noob3");
}
}
as long as the size of the collection is the same as the index it is up to, the check is not performed.
The for loop is just a simplified syntax for an iterator scan of the list. The iterator may throw an exception if the list is modified under it, but it is not guaranteed. Because of hasNext, iterators are often working one element ahead, making the first case less likely to be affected by list modification. By the time "noob2" is removed, the iterator already knows about "noob3".
Actually you should never remove collections' elements during "casual" iterating. When you have to modify your collection in some loop you have to use iterator to make these operations.
public class Test {
public static void main(String... args) {
List<String> list = new ArrayList<String>(Arrays.asList("noob1", "noob2", "noob3"));
System.out.println(list);
for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
String str = iterator.next();
if (!str.equals("noob2")) {
iterator.remove();
}
}
System.out.println(list);
}
}
I suppose the exception is thown because you are trying to change a collection you are looping on... and not because the if condition.
I suggest you to create a new list only containing the items that verify the condition. Add them to the new list and avoid to change the original collection.
It's because you are trying to remove from a Collection you are currently iterating through. Making a minor alteration you can do what you want to do:
String[] strValues = {"noob1","noob2","noob3"}; // <<< Array
List<String> list = new ArrayList<String>(Arrays.asList(strValues));
System.out.println(list);
for (String str : strValues) { // << List is duplicate of array so can iterate through array
if (!str.equals("noob2")) {
list.remove(str);
}
}
That should work. Hopefully
Well, your first case doesn't throw the Exception because, the iterator returns false for Iterator.hasNext() at index 2 as you remove the element at index 1.
Iterator<String> itr = list.iterator();
while(itr.hasNext()){
String s= itr.next();
if(s.equals("noob2")){
list.remove(s); // size of the list is 2 here
System.out.println(itr.hasNext());// this returns false as it doesn't have anything at index 2 now.(on 2nd iteration )
}
}
You can test it clearly using a simple for-loop:
for (int i=0; i<list.size(); i++) {
if (list.get(i).equals("noob2")) {
System.out.println(list.get(i));
System.out.println(list.size());
list.remove(list.get(i));
System.out.println(list.size());
}
}
Output:
[noob1, noob2, noob3]
noob2
3
2
Notice the size of the list after you remove the element, which fails after incrementing. 2<2 which is false
I am trying to designing a software that convert a flowchart into java or any other code. However I repeatedly getting the ConcurrentModificationException..
But I can't use a boolean to prevent concurrentModification, because access to the linked list happens in various places.
So as a solution I created the below adapter class. However it also throws the same exception from next method. Are there any other solution or if can, plz let me know how to modify my codes...
thank you very much...
import java.util.Iterator;
import java.util.LinkedList;
public class LinkedListAdapter<T> extends LinkedList<T>{
#Override
public boolean add(T t){
boolean b;
synchronized(this){
b = super.add(t);
}
return b;
}
#Override
public T remove(){
T t;
synchronized(this){
t = super.remove();
}
return t;
}
#Override
public Iterator<T> iterator(){
final LinkedListAdapter<T> adap = this;
return
new Iterator<T>(){
private Iterator<T> iter;
{
synchronized(adap){
iter = LinkedListAdapter.this.getIterator();
}
}
#Override
public boolean hasNext() {
boolean b;
synchronized(adap){
b = iter.hasNext();
}
return b;
}
#Override
public T next() {
T t;
synchronized(adap){
t = iter.next();
}
return t;
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
protected Iterator<T> getIterator() {
Iterator<T> iter;
synchronized(this){
iter = super.iterator();
}
return iter;
}
}
The ConcurrentModificationException is usually thrown when iterating through the list and in the same time usually another thread or even the same loop tries to modify (add / remove) the contents of the list.
Using a synchronizedList or a synchronized list still has to be synchronised externally when iterating over it.
If you use ConcurrentLinkedQueue you don't have these issues.
Queue<Task> tasks = new ConcurrentLinkedQueue<Task>();
tasks.add(task); // thread safe
tasks.remove(task2); // thread safe
for(Task t: tasks) // can iterate without a CME.
Note: if you are using a queue with another thread I suggest you use an ExecutorService as this combines a Queue with a ThreadPool and make working with "background" thread much easier.
why not use LinkedBlockingQueue? http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/LinkedBlockingQueue.html
BTW, it's not neceserally have to do with synchronization. a code like this:
for(Value v : valuesList){
valueslist.add(new Value());
}
would cause this exception as well. check your code for possible modifications of the list when it's being iterated over.
This happens when you iterate over the list and add elements to it in the body of the loop. You can remove elements safely when you use the remove() method of the iterator but not by calling any of the remove() methods of the list itself.
The solution is to copy the list before you iterate over it:
List<T> copy = new ArrayList<T>( list );
for( T e : copy ) {
... you can now modify "list" safely ...
}
Java collections are fail-fast, that means that all existing Iterators become invalid the moment the underlying collection is modified - synchronizing the modification does not stop the list from invalidating all iterators.
As a workaround you can create a copy of the list to iterate over or postpone modifications until the iteration is finished. To remove entries you can also use the iterator.remove() method which keeps the iterator itself valid.
List<X> myList = ....
List<X> myThreadSafeList = synchronizedList(myList);
synchronizedList(myList)
Notice the following statement in the JavaDoc:
It is imperative that the user manually synchronize on the returned list when iterating over it:
List list = Collections.synchronizedList(new ArrayList());
...
synchronized(list) {
Iterator i = list.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}
The answer here: Why am I getting java.util.ConcurrentModificationException? helped me a lot.
I will copy and paste it here in case anyone is looking to fix this error:
When you iterate through a list, you can't remove items from it. Doing so causes the exception.
Do:
int size = list.size();
for (int i = 0 ; i< size ; i++) {
list.add(0,"art");
list.remove(6);
System.out.println(list);
}
I'm trying to add new object to my ArrayList if it satisfy the condition.
But it got me this ConcurrentModificationExeption when I tried to run it. Hope you could help me:
public void addTaskCollection(Task t){
ListIterator<Task> iterator = this.taskCollection.listIterator();
if(this.taskCollection.isEmpty())
this.taskCollection.add(t);
while (iterator.hasNext()){
if(t.isOverlapped(iterator.next()))
this.taskCollection.add(t);
}
}
And here is the exeption error
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 Diary.addTaskCollection(Diary.java:36)
at Test.main(Test.java:50)
Java Result: 1
Replace your code with:
ListIterator<Task> iterator = this.taskCollection.listIterator();
boolean marker = false;
if(taskCollection.isEmpty())
this.taskCollection.add(t);
else {
while (iterator.hasNext()) {
if(iterator.next().isOverlapped(t) == false)
marker = true;
}
}
if (marker == true)
taskCollection.add(t);
to avoid ConcurrentModificationException.
copy the array and change the original.
It seems you encounter a race condition. Multiple threads are accessing / modifying the same collection. Use a thread-safe List implementation.
Also, you must not modifying the collection (adding / removing) while iterating on it with an Iterator.
EDIT
ConcurrentModificationExeption sounds like taskCollection is accessed and modified by multiple threads at the same time (we can not say regarding the piece of code you provide if your program is single or multi threaded). If you share taskCollection between several threads, use a thread-safe list implementation.
But, the error here is actually clearly due to the fact that you add an element to the collection between the moment you get an iterator on it and the moment you use this iterator. To fix that copy the new elements in temporary list and add them all in once at the end of the iteration.
Re-formatted Truong's answer from comments:
ListIterator<Task> iterator = this.taskCollection.listIterator();
boolean marker = false;
if(taskCollection.isEmpty())
this.taskCollection.add(t);
else {
while (iterator.hasNext()) {
if(iterator.next().isOverlapped(t) == false)
marker = true;
}
if (marker == true)
taskCollection.add(t);
}
Maintain two iterators.
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Example_v3 {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
// Insert some sample values.
list.add("Value1");
list.add("Value2");
list.add("Value3");
// Get two iterators.
Iterator<String> ite = list.iterator();
Iterator<String> ite2 = list.iterator();
// Point to the first object of the list and then, remove it.
ite.next();
ite.remove();
/* The second iterator tries to remove the first object as well. The object does
* not exist and thus, a ConcurrentModificationException is thrown. */
ite2.next();
ite2.remove();
}
}
I have an ArrayList that I want to iterate over. While iterating over it I have to remove elements at the same time. Obviously this throws a java.util.ConcurrentModificationException.
What is the best practice to handle this problem? Should I clone the list first?
I remove the elements not in the loop itself but another part of the code.
My code looks like this:
public class Test() {
private ArrayList<A> abc = new ArrayList<A>();
public void doStuff() {
for (A a : abc)
a.doSomething();
}
public void removeA(A a) {
abc.remove(a);
}
}
a.doSomething might call Test.removeA();
Two options:
Create a list of values you wish to remove, adding to that list within the loop, then call originalList.removeAll(valuesToRemove) at the end
Use the remove() method on the iterator itself. Note that this means you can't use the enhanced for loop.
As an example of the second option, removing any strings with a length greater than 5 from a list:
List<String> list = new ArrayList<String>();
...
for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {
String value = iterator.next();
if (value.length() > 5) {
iterator.remove();
}
}
From the JavaDocs of the ArrayList
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.
You are trying to remove value from list in advanced "for loop", which is not possible, even if you apply any trick (which you did in your code).
Better way is to code iterator level as other advised here.
I wonder how people have not suggested traditional for loop approach.
for( int i = 0; i < lStringList.size(); i++ )
{
String lValue = lStringList.get( i );
if(lValue.equals("_Not_Required"))
{
lStringList.remove(lValue);
i--;
}
}
This works as well.
In Java 8 you can use the Collection Interface and do this by calling the removeIf method:
yourList.removeIf((A a) -> a.value == 2);
More information can be found here
You should really just iterate back the array in the traditional way
Every time you remove an element from the list, the elements after will be push forward. As long as you don't change elements other than the iterating one, the following code should work.
public class Test(){
private ArrayList<A> abc = new ArrayList<A>();
public void doStuff(){
for(int i = (abc.size() - 1); i >= 0; i--)
abc.get(i).doSomething();
}
public void removeA(A a){
abc.remove(a);
}
}
While iterating the list, if you want to remove the element is possible. Let see below my examples,
ArrayList<String> names = new ArrayList<String>();
names.add("abc");
names.add("def");
names.add("ghi");
names.add("xyz");
I have the above names of Array list. And i want to remove the "def" name from the above list,
for(String name : names){
if(name.equals("def")){
names.remove("def");
}
}
The above code throws the ConcurrentModificationException exception because you are modifying the list while iterating.
So, to remove the "def" name from Arraylist by doing this way,
Iterator<String> itr = names.iterator();
while(itr.hasNext()){
String name = itr.next();
if(name.equals("def")){
itr.remove();
}
}
The above code, through iterator we can remove the "def" name from the Arraylist and try to print the array, you would be see the below output.
Output : [abc, ghi, xyz]
Do the loop in the normal way, the java.util.ConcurrentModificationException is an error related to the elements that are accessed.
So try:
for(int i = 0; i < list.size(); i++){
lista.get(i).action();
}
Here is an example where I use a different list to add the objects for removal, then afterwards I use stream.foreach to remove elements from original list :
private ObservableList<CustomerTableEntry> customersTableViewItems = FXCollections.observableArrayList();
...
private void removeOutdatedRowsElementsFromCustomerView()
{
ObjectProperty<TimeStamp> currentTimestamp = new SimpleObjectProperty<>(TimeStamp.getCurrentTime());
long diff;
long diffSeconds;
List<Object> objectsToRemove = new ArrayList<>();
for(CustomerTableEntry item: customersTableViewItems) {
diff = currentTimestamp.getValue().getTime() - item.timestamp.getValue().getTime();
diffSeconds = diff / 1000 % 60;
if(diffSeconds > 10) {
// Element has been idle for too long, meaning no communication, hence remove it
System.out.printf("- Idle element [%s] - will be removed\n", item.getUserName());
objectsToRemove.add(item);
}
}
objectsToRemove.stream().forEach(o -> customersTableViewItems.remove(o));
}
One option is to modify the removeA method to this -
public void removeA(A a,Iterator<A> iterator) {
iterator.remove(a);
}
But this would mean your doSomething() should be able to pass the iterator to the remove method. Not a very good idea.
Can you do this in two step approach :
In the first loop when you iterate over the list , instead of removing the selected elements , mark them as to be deleted. For this , you may simply copy these elements ( shallow copy ) into another List.
Then , once your iteration is done , simply do a removeAll from the first list all elements in the second list.
In my case, the accepted answer is not working, It stops Exception but it causes some inconsistency in my List. The following solution is perfectly working for me.
List<String> list = new ArrayList<>();
List<String> itemsToRemove = new ArrayList<>();
for (String value: list) {
if (value.length() > 5) { // your condition
itemsToRemove.add(value);
}
}
list.removeAll(itemsToRemove);
In this code, I have added the items to remove, in another list and then used list.removeAll method to remove all required items.
Instead of using For each loop, use normal for loop. for example,the below code removes all the element in the array list without giving java.util.ConcurrentModificationException. You can modify the condition in the loop according to your use case.
for(int i=0; i<abc.size(); i++) {
e.remove(i);
}
Sometimes old school is best. Just go for a simple for loop but make sure you start at the end of the list otherwise as you remove items you will get out of sync with your index.
List<String> list = new ArrayList<>();
for (int i = list.size() - 1; i >= 0; i--) {
if ("removeMe".equals(list.get(i))) {
list.remove(i);
}
}
You can also use CopyOnWriteArrayList instead of an ArrayList. This is the latest recommended approach by from JDK 1.5 onwards.
Do somehting simple like this:
for (Object object: (ArrayList<String>) list.clone()) {
list.remove(object);
}
An alternative Java 8 solution using stream:
theList = theList.stream()
.filter(element -> !shouldBeRemoved(element))
.collect(Collectors.toList());
In Java 7 you can use Guava instead:
theList = FluentIterable.from(theList)
.filter(new Predicate<String>() {
#Override
public boolean apply(String element) {
return !shouldBeRemoved(element);
}
})
.toImmutableList();
Note, that the Guava example results in an immutable list which may or may not be what you want.
for (A a : new ArrayList<>(abc)) {
a.doSomething();
abc.remove(a);
}
"Should I clone the list first?"
That will be the easiest solution, remove from the clone, and copy the clone back after removal.
An example from my rummikub game:
SuppressWarnings("unchecked")
public void removeStones() {
ArrayList<Stone> clone = (ArrayList<Stone>) stones.clone();
// remove the stones moved to the table
for (Stone stone : stones) {
if (stone.isOnTable()) {
clone.remove(stone);
}
}
stones = (ArrayList<Stone>) clone.clone();
sortStones();
}
I arrive late I know but I answer this because I think this solution is simple and elegant:
List<String> listFixed = new ArrayList<String>();
List<String> dynamicList = new ArrayList<String>();
public void fillingList() {
listFixed.add("Andrea");
listFixed.add("Susana");
listFixed.add("Oscar");
listFixed.add("Valeria");
listFixed.add("Kathy");
listFixed.add("Laura");
listFixed.add("Ana");
listFixed.add("Becker");
listFixed.add("Abraham");
dynamicList.addAll(listFixed);
}
public void updatingListFixed() {
for (String newList : dynamicList) {
if (!listFixed.contains(newList)) {
listFixed.add(newList);
}
}
//this is for add elements if you want eraser also
String removeRegister="";
for (String fixedList : listFixed) {
if (!dynamicList.contains(fixedList)) {
removeResgister = fixedList;
}
}
fixedList.remove(removeRegister);
}
All this is for updating from one list to other and you can make all from just one list
and in method updating you check both list and can eraser or add elements betwen list.
This means both list always it same size
Use Iterator instead of Array List
Have a set be converted to iterator with type match
And move to the next element and remove
Iterator<Insured> itr = insuredSet.iterator();
while (itr.hasNext()) {
itr.next();
itr.remove();
}
Moving to the next is important here as it should take the index to remove element.
List<String> list1 = new ArrayList<>();
list1.addAll(OriginalList);
List<String> list2 = new ArrayList<>();
list2.addAll(OriginalList);
This is also an option.
If your goal is to remove all elements from the list, you can iterate over each item, and then call:
list.clear()
What about of
import java.util.Collections;
List<A> abc = Collections.synchronizedList(new ArrayList<>());
ERROR
There was a mistake when I added to the same list from where I took elements:
fun <T> MutableList<T>.mathList(_fun: (T) -> T): MutableList<T> {
for (i in this) {
this.add(_fun(i)) <--- ERROR
}
return this <--- ERROR
}
DECISION
Works great when adding to a new list:
fun <T> MutableList<T>.mathList(_fun: (T) -> T): MutableList<T> {
val newList = mutableListOf<T>() <--- DECISION
for (i in this) {
newList.add(_fun(i)) <--- DECISION
}
return newList <--- DECISION
}
Just add a break after your ArrayList.remove(A) statement