I have a piece of code and i am not sure why i am getting the concurrentModificationException
import java.util.*;
import java.util.LinkedList;
import java.util.Scanner;
public class CreateList{
List<Integer> nestedList;
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
System.out.println("Enter the Nested List");
CreateList obj = new CreateList();
System.out.println(obj.createNestedList(sc.next()));
}
public List<Integer> createNestedList(String str){
List<Object> aux = new LinkedList<Object>();
nestedList = new LinkedList<Integer>();
for(int itr=0; itr<str.length();itr++){
char c = str.charAt(itr);
if(c != ']' && c != ',')
aux.add(c);
else if(c == ']'){
Object o = aux.subList(aux.lastIndexOf('[')+1,aux.size());
aux = aux.subList(0,aux.lastIndexOf('['));
aux.add(o);// THIS LINE IS THROWING THE EXCEPTION
System.out.println(o);
System.out.println(aux);
}
}
System.out.println(aux);
return nestedList;
}
}
There is no thread using this code other then the main thread. Any idea what am i missing
I think the problem is the use of subLists. Specifically
aux = aux.subList(0,aux.lastIndexOf('['));
And then later
aux.add(o);// THIS LINE IS THROWING THE EXCEPTION
This changes the size of the sublist vs the size of the original list.
The javadoc of sublist says:
The semantics of the list returned by this method become undefined if the backing list (i.e., this list) is structurally modified in any way other than via the returned list. (Structural modifications are those that change the size of this list, or otherwise perturb it in such a fashion that iterations in progress may yield incorrect results.)
The sublist instance returned by .subList() throws an exception if the modcounts of the sublist vs the original list differ.
The solution is to make a new list using the elements from the sublist
aux = new LinkedList<>(aux.subList(0,aux.lastIndexOf('[')));
You need to create another list instead of getting a sublist and adding a sublist to it.
try something like this instead:
List<T> list = new LinkedList<T>(someList.subList(0,n));
You must use a list iterator if you intend to modify the list while iterating.
List<Object> aux = new LinkedList<Object>();
...
ListIterator<Object> listIterator = aux.listIterator();
// replace the for loop with while. just to make it easier, but can be done with for loop
while(listIterator.hasNext()) {
...
listIterator.add(o);
...
}
If you replace your code with this, it should work.
Related
As I am learner of Java.. I came across the following code
public static void main(String[] args) {
ArrayList<String> a = new ArrayList<>();
a.add("1");
a.add("2");
for(String str: a){
a = new ArrayList<>();
System.out.println(str);
}
}
I guessed the answer to be
1
null (since the reference is now pointing another object)
but the answer is
1
2
I am unable understand the behavior of enhanced for loop here.
The enhanced for loop creates an Iterator to iterate of the elements of your ArrayList. Changing the a reference to refer to a new ArrayList doesn't affect the Iterator that was created by the loop.
Your loop is equivalent to
Iterator<String> iter = a.iterator();
while (iter.hasNext()) {
String str = iter.next();
a = new ArrayList<>();
System.out.println(str);
}
When you run
for(String str: a)
It gets an iterator from a, then iterates using that iterator. Reassigning a after it has the iterator will have no effect since it isn't using the a reference, it's using the iterator that a returned when the loop started.
This is because, enhanced for loop uses iterator. So changing the reference will not have any impact.
You can check different scenarios here
This question already has answers here:
Why is a ConcurrentModificationException thrown and how to debug it
(8 answers)
Closed 2 years ago.
I have this little piece of code and it gives me the concurrent modification exception. I cannot understand why I keep getting it, even though I do not see any concurrent modifications being carried out.
import java.util.*;
public class SomeClass {
public static void main(String[] args) {
List<String> s = new ArrayList<>();
ListIterator<String> it = s.listIterator();
for (String a : args)
s.add(a);
if (it.hasNext())
String item = it.next();
System.out.println(s);
}
}
To avoid the ConcurrentModificationException, you should write your code like this:
import java.util.*;
public class SomeClass {
public static void main(String[] args) {
List<String> s = new ArrayList<String>();
for(String a : args)
s.add(a);
ListIterator<String> it = s.listIterator();
if(it.hasNext()) {
String item = it.next();
}
System.out.println(s);
}
}
A java.util.ListIterator allows you to modify a list during iteration, but not between creating it and using it.
I cannot understand why I keep getting it, even though I do not see any concurrent modifications being carried out.
Between creating the iterator and starting to use the iterator, you added arguments to the list that is to be iterated. This is a concurrent modification.
ListIterator<String> it = s.listIterator();
for (String a : args)
s.add(a); // concurrent modification here
if (it.hasNext())
String item = it.next(); // exception thrown here
Create the iterator AFTER you've finished adding elements to the list:
for (String a : args)
s.add(a);
ListIterator<String> it = s.listIterator();
if (it.hasNext())
String item = it.next();
From the JavaDoc: for ConcurrentModificatoinException: "it is not generally permssible for one thread to modify a Collection while another thread is iterating over it".
It simply means that if you still have an open iterator, you aren't allowed to modify the list because the iterator loop will break. Try moving ListIterator<String> it = s.listIterator(); till after the for loop.
You are not allowed to continue iterating over an iterator after the underlying list is modified. Here you create the iterator before adding a few items to s, and then proceed to do a hasNext() and a next() on it after the additions, leading to the ConcurrentModificationException
If the above solutions doesn't work properly. You can use old for-loop for iterating a List at the same time adding new items. See the example below:
import java.util.*;
public class SomeClass {
public static void main(String[] args) {
ArrayList<AClass> aList = new ArrayList<AClass>(); // we will iterate this
// this will cause ConcurrentModificationException.
// Since we are iterating the list, at the same time modifying it.
/*for(AClass a: aList){
aList.add(someMethod(a));
}*/
// old fashion for-loop will help
int limit = aList.size();
for(int i=0; ctr<limit; ++i){
AClass a = aList.get(i);
aList.add(someMethod(a));
}
}
}
to understand this lets look at source of HashMap implementation:
public class HashMap<K, V> extends AbstractMap<K, V> implements Cloneable, Serializable{
which contains HashIterator as below:
private abstract class HashIterator {
...
int expectedModCount = modCount;
...
HashMapEntry<K, V> nextEntry() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
....
}
every time you create a iterator:
a counter expectedModCount is created and is set to value of modCount as entry checkpoint
modCount is incremented in cases of use put/get (add/remove)
nextEntry method of iterator is checking this value with current modCount if they are different concurrent modification exception is throw
to avoid this u can:
convert map to an array (not recommended for large maps)
use concurrency map or list classes (CopyOnWriteArrayList / ConcurrentMap)
lock map (this approach removes benefits of multithreading)
this will allow you to iterate and add or remove elements at the same time without rising an exception
Concurrency map/list iterator is a "weakly consistent" iterator that will
never throw ConcurrentModificationException, and guarantees to
traverse elements as they existed upon construction of the iterator,
and may (but is not guaranteed to) reflect any modifications
subsequent to construction.
More info on CopyOnWriteArrayList
ConcurrentModificationException may arise in both single threaded environment and multi-threaded environment.
The main catch is that all the general purpose iterators (like the one used in ArrayList) are all FailFast iterators, which fails when we try to modify one list if one iterator is already iterating over it.
Solution - > Use CopyOnWriteArrayList if such scenario is needed by the requirement rather than using ArrayList.
For a complete demo for this, below mentioned code can be used.
We just need to change the implementation from CopyOnWriteArrayList to ArrayList.
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* #author narif
*
*/
public class TestApp {
/**
* #param args
*/
public static void main(String[] args) {
List<String> testList = new ArrayList<>();
testList.add("abc");
testList.add("abc");
testList.add("abc");
testList.add("abc");
testList.add("abc");
testList.add("abc");
testList.add("abc");
testList.add("abc");
testList.add("abc");
testList.add("abc");
testList.add("abc");
testList.add("abc");
testList.add(6, "abcAtindex6");
int size = testList.size();
System.out.println("The Current List (ArrayList) is: " + testList);
System.out.println("The size of the List (ArrayList) is: " + size);
/* Comment the below lines to get the ConcurrentModificationException */
testList = new CopyOnWriteArrayList<>(testList);
for (String value : testList) {
System.out.println("The Value from ForEach Loop is: " + value);
/*
* Concurrent modification is happening here
* One iterator is iterating over the list while we are trying to add new values to
* the list so the results of the iteration are undefined under these circumstances.
* So teh fail fast iterators will fail and will throw the ConcurrentModificationException.
*/
testList.add("valueFromForLoop");
testList.add("anotherValueFromForEachLoop");
}
Iterator<String> it = testList.iterator();
while (it.hasNext()) {
String abc = it.next();
System.out.println(abc);
testList.add("Value from Iterator1");
testList.add("Value from Iterator2");
testList.add("Value from Iterator3");
testList.add("Value from Iterator4");
}
System.out.println("Did the modificationa and all after conevrting the ArrayList to CopyOnWriteArrayList.");
System.out.println("Calling the method to get the new List..");
testList = new CopyOnWriteArrayList<>(getTheList(testList));
for (String value : testList) {
System.out.println("The value returned from method is : " + value);
}
}
private static List<String> getTheList(List<String> pList) {
List<String> list = new CopyOnWriteArrayList<>(pList);
int i = 0;
for (String lValue : list) {
System.out.println("The list Passed is " + list);
i++;
list.add("localVaueFromMethod" + i);
list.removeAll(pList);
}
return list;
}
}
For more inifo follow this link this may be helpful alot ConcurrentModificationException Java Docs
This didn't work:
LinkedList<String> linkedList = new LinkedList<String>();
ListIterator listIterator = linkedList.listIterator();
linkedList.add("aa");
linkedList.add("bb");
This worked:
LinkedList<String> linkedList = new LinkedList<String>();
linkedList.add("aa");
linkedList.add("bb");
ListIterator listIterator = linkedList.listIterator();
Have a look at oracle documentation page.
public class ConcurrentModificationException
extends RuntimeException
This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible
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 throw this exception.
In your case, you have modified the collection after creating the iterator and hence you have encountered the exception.
If you change your code as per Stephen C answer, you won't get this error.
We are given a list of words in the form of an ArrayList as follows:
public ArrayList<String> getListOfStrings(){
ArrayList<String> list = new ArrayList<String>();
list.add("This");
list.add("is");
list.add("an");
list.add("exercise");
list.add("to");
list.add("illustrate");
list.add("the");
list.add("use");
list.add("of");
list.add("ArrayLists");
list.add(".");
return list;
}
How do I write a method that removes all words in that list (i.e. all the objects in the ArrayList) that have the length "len" entered by the user?
I already wrote a method that lists all the words of length "len" entered by the user, and it works, it's as follows:
public ArrayList<String>getWordsWithLength(int len, ArrayList<String> lijst){
ArrayList<String> list = new ArrayList<String>();
for(String woord: lijst){
if(woord.length()==len){
list.add(woord);
}
}
return(list);
}
But as a beginner in java, I'm stuck on how to remove the words of length "len". Please help!
(I am under the impression that you start by removing them from the end of the list, back-to-front as it were)
The way your currently iterating through the list wont allow you to remove it with an exception but an iterator would.
Iterator<String> it = list.iterator();
while(it.hasNext()) {
if([Condition]) {
it.remove();
}
}
Your method can already serve as a removal, just change the == to a !=
public ArrayList<String> getStringsWithoutEqualLength(int len, ArrayList<String> lijst){
ArrayList<String> list = new ArrayList<String>();
for(String woord: lijst){
if(woord.length() != len){
list.add(woord);
}
}
return(list);
}
If what you are attempting to do is remove the elements from lijst, then just reassign the returned list to it.
ArrayList<String> yourList = ...;
yourList = instance.getStringsWithoutEqualLength(someLength, yourList);
You have effectively removed the longer elements and done it faster than if you had used an Iterator. Every time you remove with an Iterator, you have to resize your backing array.
You have to remove values from a List by using an Iterator to prevent a ConcurrentModificationException.
List<String> myList = getListOfStrings();
Iterator<String> it = myList.iterator();
while (it.hasNext()) {
if(it.next().length() == 3){
it.remove();
}
}
You can even use the same method by adding a boolean parameter.
public ArrayList<String>getWordsWithLength(int len, ArrayList<String> lijst, boolean complement){
ArrayList<String> list = new ArrayList<String>();
for(String woord: lijst){
if((woord.length()==len) != complement){
list.add(woord);
}
}
return(list);
}
If you pass in complement as true, if will give you everything with that doesn't have length == len. complement as false will behave as usual.
While I think that #SotiriosDelimanolis's answer is probably what you should use, I also wanted to point out that with Java 8 you can easily do this using a Stream and a Predicate to filter on:
List<String> list2 = list.stream()
.filter(s -> s.length() != 3)
.collect(Collectors.toList());
Here's a full test class:
import java.util.*;
import java.util.stream.*;
class Test {
public static void main(String args[]) {
ArrayList<String> list = new ArrayList<String>();
list.add("This");
list.add("is");
list.add("an");
list.add("exercise");
list.add("to");
list.add("illustrate");
list.add("the");
list.add("use");
list.add("of");
list.add("ArrayLists");
list.add(".");
System.out.println(list);
List<String> list2 = list.stream()
.filter(s -> s.length() != 3)
.collect(Collectors.toList());
System.out.println(list2);
}
}
and my test output:
$ java Test
[This, is, an, exercise, to, illustrate, the, use, of, ArrayLists, .]
[This, is, an, exercise, to, illustrate, of, ArrayLists, .]
in Scala you'd just do
list.filter(_.length != len)
Can somebody please explain me why I can't cast List<> to ArrayList<> with first approach and I do with second one? Thank you.
First approach:
ArrayList<Task> tmp = ((ArrayList<Task>)mTrackytAdapter.getAllTasks(token));
Second approach:
ArrayList<Task> tmp = new ArrayList<Task>(mTrackytAdapter.getAllTasks(token));
When you do the second one, you're making a new arraylist, you're not trying to pretend the other list is an arraylist.
I mean, what if the original list is implemented as a linkedlist, or some custom list? You won't know. The second approach is preferred if you really need to make an arraylist from the result. But you can just leave it as a list, that's one of the best advantages of using Interfaces!
When you are using second approach you are initializing arraylist with its predefined values.
Like generally we do
**ArrayList listofStrings = new ArrayList<>();
**
Let's say you have an array with values, now you want to convert this array into arraylist.
you need to first get the list from the array using Arrays utils.
Because the ArrayList is concrete type that implement List interface. It is not guaranteed that method asList, will return this type of implementation.
List<String> listofOptions = (List<String>) Arrays.asList(options);
then you can user constructoru of an arraylist to instantiate with predefined values.
ArrayList<String> arrlistofOptions = new ArrayList<String>(list);
So your second approach is working that you have passed values which will intantiate arraylist with the list elements.
More over
ArrayList that is returned from Arrays.asList is not an actual arraylist, it is just a wrapper which doesnt allows any modification in the list.
If you try to add or remove over Arrays.asList it will give you
UnsupportedOperationException
Try running the following code:
List<String> listOfString = Arrays.asList("Hello", "World");
ArrayList<String> arrayListOfString = new ArrayList(listOfString);
System.out.println(listOfString.getClass());
System.out.println(arrayListOfString.getClass());
You'll get the following result:
class java.util.Arrays$ArrayList
class java.util.ArrayList
So, that means they're 2 different classes that aren't extending each other. java.util.Arrays$ArrayList signifies the private class named ArrayList (inner class of Arrays class) and java.util.ArrayList signifies the public class named ArrayList. Thus, casting from java.util.Arrays$ArrayList to java.util.ArrayList and vice versa are irrelevant/not available.
The second approach is clearly wrong if you want to cast. It instantiate a new ArrayList.
However the first approach should work just fine, if and only if getAllTasks return an ArrayList.
It is really needed for you to have an ArrayList ? isn't the List interface enough ? What you are doing can leads to Runtime Exception if the type isn't correct.
If getAllTasks() return an ArrayList you should change the return type in the class definition and then you won't need a cast and if it's returning something else, you can't cast to ArrayList.
Just try this :
ArrayList<SomeClass> arrayList;
public SomeConstructor(List<SomeClass> listData) {
arrayList.addAll(listData);
}
You can cast List<> to ArrayList<> if you understand what you doing. Java compiler won't block it.
But:
It's bad practice to casting parent type to child type (or interface to implementation type) without checking.
This way better:
if (list instanceof ArrayList<Task>) {
ArrayList<Task> arraylist = (ArrayList<Task>) list;
}
Maybe you don't need implementation type as reference. Look SonarQube warning https://sbforge.org/sonar/rules/show/squid:S1319. You can avoid this casting in the most cases.
You can use Guava method:
ArrayList<Task> arraylist = Lists.newArrayList(list);
The first approach is trying to cast the list but this would work only if the List<> were an ArrayList<>. That is not the case. So you need the second approach, that is building a new ArrayList<> with the elements of the List<>
Because in the first one , you're trying to convert a collection to an ArrayList.
In the 2nd one , you just use the built in constructor of ArrayList
May be:
ArrayList<ServiceModel> services = new ArrayList<>(parking.getServices());
intent.putExtra("servicios",services);
import java.util.List;
import java.util.Arrays;
import java.util.*;
public class Merge
{
public static void main(String[] args) {
// This is normal way
// List<Integer> l1 = new ArrayList<Integer>(); l1.add(2); l1.add(5); l1.add(10); l1.add(22);
// List<Integer> l2 = new ArrayList<Integer>(); l2.add(3); l2.add(8); l2.add(15);
//Array.asList only have the list interface, but ArrayList is inherited from List Interface with few more property like ArrayList.remove()
List<Integer> templ1 = Arrays.asList(2,5,10,22);
List<Integer> templ2 = Arrays.asList(3,8,12);
//So creation of ArrayList with the given list is required, then only ArrayList.remove function works.
List<Integer> l1 = new ArrayList<Integer>(templ1);
List<Integer> l2 = new ArrayList<Integer>(templ2);
List<Integer> l3 = new ArrayList<Integer>();
Iterator itr1 = l1.iterator();
while(itr1.hasNext()){
int x = (Integer) itr1.next();
Iterator itr2 = l2.iterator();
while(itr2.hasNext()) {
int y = (Integer) itr2.next();
if(x < y) {
l3.add(x);
break;
}
else{
l3.add(y);
itr2.remove();
}
}
}
Iterator it = l1.iterator();
while (it.hasNext()){
int k = (Integer) it.next();
if (l3.contains(k)){
continue;
}
else{
l3.add(k);
System.out.println(k);
}
}
Iterator itr2 = l2.iterator();
while (itr2.hasNext()){
int k = (Integer) itr2.next();
l3.add(k);
}
System.out.println(l3);
}
}
This question already has answers here:
Why is a ConcurrentModificationException thrown and how to debug it
(8 answers)
Closed 2 years ago.
I have this little piece of code and it gives me the concurrent modification exception. I cannot understand why I keep getting it, even though I do not see any concurrent modifications being carried out.
import java.util.*;
public class SomeClass {
public static void main(String[] args) {
List<String> s = new ArrayList<>();
ListIterator<String> it = s.listIterator();
for (String a : args)
s.add(a);
if (it.hasNext())
String item = it.next();
System.out.println(s);
}
}
To avoid the ConcurrentModificationException, you should write your code like this:
import java.util.*;
public class SomeClass {
public static void main(String[] args) {
List<String> s = new ArrayList<String>();
for(String a : args)
s.add(a);
ListIterator<String> it = s.listIterator();
if(it.hasNext()) {
String item = it.next();
}
System.out.println(s);
}
}
A java.util.ListIterator allows you to modify a list during iteration, but not between creating it and using it.
I cannot understand why I keep getting it, even though I do not see any concurrent modifications being carried out.
Between creating the iterator and starting to use the iterator, you added arguments to the list that is to be iterated. This is a concurrent modification.
ListIterator<String> it = s.listIterator();
for (String a : args)
s.add(a); // concurrent modification here
if (it.hasNext())
String item = it.next(); // exception thrown here
Create the iterator AFTER you've finished adding elements to the list:
for (String a : args)
s.add(a);
ListIterator<String> it = s.listIterator();
if (it.hasNext())
String item = it.next();
From the JavaDoc: for ConcurrentModificatoinException: "it is not generally permssible for one thread to modify a Collection while another thread is iterating over it".
It simply means that if you still have an open iterator, you aren't allowed to modify the list because the iterator loop will break. Try moving ListIterator<String> it = s.listIterator(); till after the for loop.
You are not allowed to continue iterating over an iterator after the underlying list is modified. Here you create the iterator before adding a few items to s, and then proceed to do a hasNext() and a next() on it after the additions, leading to the ConcurrentModificationException
If the above solutions doesn't work properly. You can use old for-loop for iterating a List at the same time adding new items. See the example below:
import java.util.*;
public class SomeClass {
public static void main(String[] args) {
ArrayList<AClass> aList = new ArrayList<AClass>(); // we will iterate this
// this will cause ConcurrentModificationException.
// Since we are iterating the list, at the same time modifying it.
/*for(AClass a: aList){
aList.add(someMethod(a));
}*/
// old fashion for-loop will help
int limit = aList.size();
for(int i=0; ctr<limit; ++i){
AClass a = aList.get(i);
aList.add(someMethod(a));
}
}
}
to understand this lets look at source of HashMap implementation:
public class HashMap<K, V> extends AbstractMap<K, V> implements Cloneable, Serializable{
which contains HashIterator as below:
private abstract class HashIterator {
...
int expectedModCount = modCount;
...
HashMapEntry<K, V> nextEntry() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
....
}
every time you create a iterator:
a counter expectedModCount is created and is set to value of modCount as entry checkpoint
modCount is incremented in cases of use put/get (add/remove)
nextEntry method of iterator is checking this value with current modCount if they are different concurrent modification exception is throw
to avoid this u can:
convert map to an array (not recommended for large maps)
use concurrency map or list classes (CopyOnWriteArrayList / ConcurrentMap)
lock map (this approach removes benefits of multithreading)
this will allow you to iterate and add or remove elements at the same time without rising an exception
Concurrency map/list iterator is a "weakly consistent" iterator that will
never throw ConcurrentModificationException, and guarantees to
traverse elements as they existed upon construction of the iterator,
and may (but is not guaranteed to) reflect any modifications
subsequent to construction.
More info on CopyOnWriteArrayList
ConcurrentModificationException may arise in both single threaded environment and multi-threaded environment.
The main catch is that all the general purpose iterators (like the one used in ArrayList) are all FailFast iterators, which fails when we try to modify one list if one iterator is already iterating over it.
Solution - > Use CopyOnWriteArrayList if such scenario is needed by the requirement rather than using ArrayList.
For a complete demo for this, below mentioned code can be used.
We just need to change the implementation from CopyOnWriteArrayList to ArrayList.
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* #author narif
*
*/
public class TestApp {
/**
* #param args
*/
public static void main(String[] args) {
List<String> testList = new ArrayList<>();
testList.add("abc");
testList.add("abc");
testList.add("abc");
testList.add("abc");
testList.add("abc");
testList.add("abc");
testList.add("abc");
testList.add("abc");
testList.add("abc");
testList.add("abc");
testList.add("abc");
testList.add("abc");
testList.add(6, "abcAtindex6");
int size = testList.size();
System.out.println("The Current List (ArrayList) is: " + testList);
System.out.println("The size of the List (ArrayList) is: " + size);
/* Comment the below lines to get the ConcurrentModificationException */
testList = new CopyOnWriteArrayList<>(testList);
for (String value : testList) {
System.out.println("The Value from ForEach Loop is: " + value);
/*
* Concurrent modification is happening here
* One iterator is iterating over the list while we are trying to add new values to
* the list so the results of the iteration are undefined under these circumstances.
* So teh fail fast iterators will fail and will throw the ConcurrentModificationException.
*/
testList.add("valueFromForLoop");
testList.add("anotherValueFromForEachLoop");
}
Iterator<String> it = testList.iterator();
while (it.hasNext()) {
String abc = it.next();
System.out.println(abc);
testList.add("Value from Iterator1");
testList.add("Value from Iterator2");
testList.add("Value from Iterator3");
testList.add("Value from Iterator4");
}
System.out.println("Did the modificationa and all after conevrting the ArrayList to CopyOnWriteArrayList.");
System.out.println("Calling the method to get the new List..");
testList = new CopyOnWriteArrayList<>(getTheList(testList));
for (String value : testList) {
System.out.println("The value returned from method is : " + value);
}
}
private static List<String> getTheList(List<String> pList) {
List<String> list = new CopyOnWriteArrayList<>(pList);
int i = 0;
for (String lValue : list) {
System.out.println("The list Passed is " + list);
i++;
list.add("localVaueFromMethod" + i);
list.removeAll(pList);
}
return list;
}
}
For more inifo follow this link this may be helpful alot ConcurrentModificationException Java Docs
This didn't work:
LinkedList<String> linkedList = new LinkedList<String>();
ListIterator listIterator = linkedList.listIterator();
linkedList.add("aa");
linkedList.add("bb");
This worked:
LinkedList<String> linkedList = new LinkedList<String>();
linkedList.add("aa");
linkedList.add("bb");
ListIterator listIterator = linkedList.listIterator();
Have a look at oracle documentation page.
public class ConcurrentModificationException
extends RuntimeException
This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible
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 throw this exception.
In your case, you have modified the collection after creating the iterator and hence you have encountered the exception.
If you change your code as per Stephen C answer, you won't get this error.