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);
}
Related
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());
}
}
Note: I am aware of the Iterator#remove() method.
In the following code sample, I don't understand why the List.remove in main method throws ConcurrentModificationException, but not in the remove method.
public class RemoveListElementDemo {
private static final List<Integer> integerList;
static {
integerList = new ArrayList<Integer>();
integerList.add(1);
integerList.add(2);
integerList.add(3);
}
public static void remove(Integer toRemove) {
for(Integer integer : integerList) {
if(integer.equals(toRemove)) {
integerList.remove(integer);
}
}
}
public static void main(String... args) {
remove(Integer.valueOf(2));
Integer toRemove = Integer.valueOf(3);
for(Integer integer : integerList) {
if(integer.equals(toRemove)) {
integerList.remove(integer);
}
}
}
}
Here's why:
As it is says in the 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.
This check is done in the next() method of the iterator (as you can see by the stacktrace). But we will reach the next() method only if hasNext() delivered true, which is what is called by the for each to check if the boundary is met. In your remove method, when hasNext() checks if it needs to return another element, it will see that it returned two elements, and now after one element was removed the list only contains two elements. So all is peachy and we are done with iterating. The check for concurrent modifications does not occur, as this is done in the next() method which is never called.
Next we get to the second loop. After we remove the second number the hasNext method will check again if can return more values. It has returned two values already, but the list now only contains one. But the code here is:
public boolean hasNext() {
return cursor != size();
}
1 != 2, so we continue to the next() method, which now realizes that someone has been messing with the list and fires the exception.
Hope that clears your question up.
Summary
List.remove() will not throw ConcurrentModificationException when it removes the second last element from the list.
One way to handle it it to remove something from a copy of a Collection (not Collection itself), if applicable. Clone the original collection it to make a copy via a Constructor.
This exception may be thrown by methods that have detected concurrent
modification of an object when such modification is not permissible.
For your specific case, first off, i don't think final is a way to go considering you intend to modify the list past declaration
private static final List<Integer> integerList;
Also consider modifying a copy instead of the original list.
List<Integer> copy = new ArrayList<Integer>(integerList);
for(Integer integer : integerList) {
if(integer.equals(remove)) {
copy.remove(integer);
}
}
The forward/iterator method does not work when removing items. You can remove the element without error, but you will get a runtime error when you try to access removed items. You can't use the iterator because as pushy shows it will cause a ConcurrentModificationException, so use a regular for loop instead, but step backwards through it.
List<Integer> integerList;
integerList = new ArrayList<Integer>();
integerList.add(1);
integerList.add(2);
integerList.add(3);
int size= integerList.size();
//Item to remove
Integer remove = Integer.valueOf(3);
A solution:
Traverse the array in reverse order if you are going to remove a list element. Simply by going backwards through the list you avoid visiting an item that has been removed, which removes the exception.
//To remove items from the list, start from the end and go backwards through the arrayList
//This way if we remove one from the beginning as we go through, then we will avoid getting a runtime error
//for java.lang.IndexOutOfBoundsException or java.util.ConcurrentModificationException as when we used the iterator
for (int i=size-1; i> -1; i--) {
if (integerList.get(i).equals(remove) ) {
integerList.remove(i);
}
}
This snippet will always throw a ConcurrentModificationException.
The rule is "You may not modify (add or remove elements from the list) while iterating over it using an Iterator (which happens when you use a for-each loop)".
JavaDocs:
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.
Hence if you want to modify the list (or any collection in general), use iterator, because then it is aware of the modifications and hence those will be handled properly.
Hope this helps.
I had that same problem but in case that I was adding en element into iterated list.
I made it this way
public static void remove(Integer remove) {
for(int i=0; i<integerList.size(); i++) {
//here is maybe fine to deal with integerList.get(i)==null
if(integerList.get(i).equals(remove)) {
integerList.remove(i);
}
}
}
Now everything goes fine because you don't create any iterator over your list, you iterate over it "manually". And condition i < integerList.size() will never fool you because when you remove/add something into List size of the List decrement/increment..
Hope it helps, for me that was solution.
If you use copy-on-write collections it will work; however when you use list.iterator(), the returned Iterator will always reference the collection of elements as it was when ( as below )
list.iterator() was called, even if another thread modifies the collection. Any
mutating methods called on a copy-on-write–based Iterator or ListIterator
(such as add, set, or remove) will throw an UnsupportedOperationException.
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class RemoveListElementDemo {
private static final List<Integer> integerList;
static {
integerList = new CopyOnWriteArrayList<>();
integerList.add(1);
integerList.add(2);
integerList.add(3);
}
public static void remove(Integer remove) {
for(Integer integer : integerList) {
if(integer.equals(remove)) {
integerList.remove(integer);
}
}
}
public static void main(String... args) {
remove(Integer.valueOf(2));
Integer remove = Integer.valueOf(3);
for(Integer integer : integerList) {
if(integer.equals(remove)) {
integerList.remove(integer);
}
}
}
}
This runs fine on Java 1.6
~ % javac RemoveListElementDemo.java
~ % java RemoveListElementDemo
~ % cat RemoveListElementDemo.java
import java.util.*;
public class RemoveListElementDemo {
private static final List<Integer> integerList;
static {
integerList = new ArrayList<Integer>();
integerList.add(1);
integerList.add(2);
integerList.add(3);
}
public static void remove(Integer remove) {
for(Integer integer : integerList) {
if(integer.equals(remove)) {
integerList.remove(integer);
}
}
}
public static void main(String... args) {
remove(Integer.valueOf(2));
Integer remove = Integer.valueOf(3);
for(Integer integer : integerList) {
if(integer.equals(remove)) {
integerList.remove(integer);
}
}
}
}
~ %
In my case I did it like this:
int cursor = 0;
do {
if (integer.equals(remove))
integerList.remove(cursor);
else cursor++;
} while (cursor != integerList.size());
Change Iterator for each into for loop to solve.
And the Reason is:
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.
--Referred Java Docs.
Check your code man....
In the main method you are trying to remove the 4th element which is not there and hence the error.
In the remove() method you are trying to remove the 3rd element which is there and hence no error.
class Nodes has getNodes() method, which is not synchronized. But List<Node> nodes - is synchronized. Many threads could be connected to it, changing nodes in it.
Like this:
class Nodes {
List<Node> nodes = Collections.synchronizedList(new ArrayList<Node>() );
public List<Nodes> getNodes() { return nodes; }
...
}
Client code:
Nodes nodes;
synchronized(nodes) {
for(Node node: nodes.getNodes()) {
...
}
}
I do not have interrogation tests for that, but:
Should I use while(iterator.hasNext()) { var = iterator.next() } instead of for-loop ?
Because I know that when I try to delete nodes.remove(node) inside for-loop it fails with ConcurentModificationException.
EDIT: (related issue)
If iterator is good stuff to use, then having this code (client code):
Iterator<Node> iter = nodes.getNodes().iterator();
while (iter.hasNext()) { // line 1
Node node = iter.next(); // line 2
}
It is not safe anyway:
1. thread1 goes to line 1, hoping that now iter would return him next() value.
2. but at that moment thread2 delete that value.
3. thread1 has Exception and fails.
Does it mean that I should do locking on client side anyway. This is what I don't want to do.
One of the solutions I have:
while (iter.hasNext()) {
try {
Node node = iter.next();
...
} catch (NoSuchElementException ex) {continue;} // handle exception - do more try
}
EDIT:
Answer for my case was: to use CopyOnWriteArrayList. I can even stay with for-loop with it.
But another option: Just return client a copy of the list to let them know whatever they want with it. Because it is kind of strange (inconsistent) providing 'snapshot iterator' AND real data in the list at the same time.
Iterator.remove is the only safe way to modify a collection during iteration
Source: The Collection Interface tutorial
You should use an iterator like you have suggest, but instead of doing a nodes.delete() (which is really a nodes.remove(...) ) you should instead do iterator.remove()
You have updated your question. Here's an updated answer addressing the 'atomicity' of the iterator. If you want your iterator to have a 'snapshot' of the values at the time it (the iterator) was created, then you can use the Concurrent set of collections in java.util.concurrent: like CopyOnWriteArrayList
What is even better:
To use:
private List<Node> defensiveCopyNodeList() {
List<Node> nodesListCopy = Lists.newLinkedList();
synchronized (nodesList) {
nodesListCopy = ImmutableList.copyOf(nodesList); // Google [Guava lib][1]
}
return nodesListCopy;
}
Then in getter:
public List<Node> getNodes() {
return defensiveCopyNodeList();
}
Then it allows us to use safely not only iterator but and data itself.
Is there a "computationally" quick way to get the count of an iterator?
int i = 0;
for ( ; some_iterator.hasNext() ; ++i ) some_iterator.next();
... seems like a waste of CPU cycles.
Using Guava library:
int size = Iterators.size(iterator);
Internally it just iterates over all elements so its just for convenience.
If you've just got the iterator then that's what you'll have to do - it doesn't know how many items it's got left to iterate over, so you can't query it for that result. There are utility methods that will seem to do this efficiently (such as Iterators.size() in Guava), but underneath they're just consuming the iterator and counting as they go, the same as in your example.
However, many iterators come from collections, which you can often query for their size. And if it's a user made class you're getting the iterator for, you could look to provide a size() method on that class.
In short, in the situation where you only have the iterator then there's no better way, but much more often than not you have access to the underlying collection or object from which you may be able to get the size directly.
Your code will give you an exception when you reach the end of the iterator. You could do:
int i = 0;
while(iterator.hasNext()) {
i++;
iterator.next();
}
If you had access to the underlying collection, you would be able to call coll.size()...
EDIT
OK you have amended...
You will always have to iterate. Yet you can use Java 8, 9 to do the counting without looping explicitely:
Iterable<Integer> newIterable = () -> iter;
long count = StreamSupport.stream(newIterable.spliterator(), false).count();
Here is a test:
public static void main(String[] args) throws IOException {
Iterator<Integer> iter = Arrays.asList(1, 2, 3, 4, 5).iterator();
Iterable<Integer> newIterable = () -> iter;
long count = StreamSupport.stream(newIterable.spliterator(), false).count();
System.out.println(count);
}
This prints:
5
Interesting enough you can parallelize the count operation here by changing the parallel flag on this call:
long count = StreamSupport.stream(newIterable.spliterator(), *true*).count();
Using Guava library, another option is to convert the Iterable to a List.
List list = Lists.newArrayList(some_iterator);
int count = list.size();
Use this if you need also to access the elements of the iterator after getting its size. By using Iterators.size() you no longer can access the iterated elements.
If all you have is the iterator, then no, there is no "better" way. If the iterator comes from a collection you could as that for size.
Keep in mind that Iterator is just an interface for traversing distinct values, you would very well have code such as this
new Iterator<Long>() {
final Random r = new Random();
#Override
public boolean hasNext() {
return true;
}
#Override
public Long next() {
return r.nextLong();
}
#Override
public void remove() {
throw new IllegalArgumentException("Not implemented");
}
};
or
new Iterator<BigInteger>() {
BigInteger next = BigInteger.ZERO;
#Override
public boolean hasNext() {
return true;
}
#Override
public BigInteger next() {
BigInteger current = next;
next = next.add(BigInteger.ONE);
return current;
}
#Override
public void remove() {
throw new IllegalArgumentException("Not implemented");
}
};
There is no more efficient way, if all you have is the iterator. And if the iterator can only be used once, then getting the count before you get the iterator's contents is ... problematic.
The solution is either to change your application so that it doesn't need the count, or to obtain the count by some other means. (For example, pass a Collection rather than Iterator ...)
for Java 8 you could use,
public static int getIteratorSize(Iterator iterator){
AtomicInteger count = new AtomicInteger(0);
iterator.forEachRemaining(element -> {
count.incrementAndGet();
});
return count.get();
}
To get the size of an Iterable
Iterable<Users> users = usersRepository.findUsersByLocation("IND");
Now assert the size of users of Type Iterable
assertEquals(2, ((Collection<Users>)users).size());
To get quickly the size :
[...iterator].length
iterator object contains the same number of elements what your collection contained.
List<E> a =...;
Iterator<E> i = a.iterator();
int size = a.size();//Because iterators size is equal to list a's size.
But instead of getting the size of iterator and iterating through index 0 to that size, it is better to iterate through the method next() of the iterator.
Okay, so I'm supposed to implement a set that contains elements of type Object with no duplicates which means that I need to compare each new element with the previous elements in the set. The set has its own class and has a method for inserting a new element.
My question is: How do I use the iterator I wrote below to compare all the entries in the set with the proposed element to add?
class SetIterator implements MyIterator {
private ArraySet arr; //ArraySet is the name of the Set class
private int n;
SetIterator(ArraySet myArraySet)
{
arr = myArraySet;
n = 0;
}
#Override
public boolean hasNext()
{
return (n <= arr.size());
}
#Override
public Object next()
{
if (hasNext())
return arr[n++];
}
}
Thanks!
You'd need something like this in ArraySet.java.
public Iterator iterator()
{
return new SetIterator(this);
}
public boolean add(Object o)
{
for (Object item : this)
if (o.equals(next)) return false;
}
// add code to put o in the array
return true;
}
The for loop is translated by the compiler to something like this:
Iterator it = this.iterator();
while (it.hasNext())
{
Object item = it.next();
if (o.equals(next)) return false;
}
The implementation of Set should guarantee no-duplication rather than the Iterator.
That is, your Set.add() and its constructor with Collection as argument should guarantee no-duplication.
The Iterator just implements hasNext(), next(), and remove().
If Iterator takes care of duplication checking, your Set will violate java.util.Set contract. Moreover, the Iterator will take two responsibilities—checking duplication and traversing, that violates “Single Responsibily Principle”.
Yes, I just want an example on how to use that iterator instead of a for loop or a while loop.
You pretty much have to use some kind of loop to use a Iterator. Here is the basic pattern:
Iterator it = ... // instantiate the iterator
while (it.hasNext()) {
Object obj = it.next();
... // do something with obj
}
If the collection object (e.g. your set of objects) implements Iterable then you can use the new for loop syntax; e.g.
for (Object obj : yourSet) {
... // do something with obj
}
Of course, there are other ways to express this, but they all involve (somewhere) a loop of some kind to pull the objects from the iterator.