I have a problem iterating my priority queue which cost Concurrentmodificationexception.
code for iterating:
Queue<Patient> pq = new PriorityQueue<Patient>();
Iterator<Patient> it = pq.iterator();
while(iter.hasNext()){
Patient current = iter.next();
if(current.getName().equals(patientName)){
pq.remove(p);
}
}
There error says that iter.next() cost Concurrentmodificationexception.
May i please know how to resolve this? i have search the internet but the still cant find a solution to this.
Change your code to following for solving it -
Queue<Patient> pq = new PriorityQueue<Patient>();
Iterator<Patient> iter = pq.iterator();
while(iter.hasNext()){
Patient current = iter.next();
if(current.getName().equals(patientName)){
iter.remove();
}
}
Explanation ConcurrentModificationException is thrown from next() method of iterator, if there is any structural change in the underlying collection (in your case Queue) i.e. any element is added or removed in the queue directly. It is called Fail Fast Iterator.
Try to use ConcurrentLinkedQueue instead of PriorityQueue
Acording to: https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentLinkedQueue.html
Beware that, unlike in most collections, the size method is NOT a constant-time operation. Because of the asynchronous nature of these queues, determining the current number of elements requires a traversal of the elements, and so may report inaccurate results if this collection is modified during traversal.
Since Java8, you can remove using removeIf which is part of Collection contract.
Given that removeIf method takes a predicate, your code could be as simple as :
priorityQueue.removeIf(patient -> patient.getName().equals(patientName));
As for the Concurrent exception you had, this simply happened because you tried to remove calling PriorityQueue#remove directly while you were already iterating which would make the iterator obsolete. The proper way to remove when iterating is by using Iterator#next and then Iterator#remove (this is actually what de default implementation of removeIf does).
Related
I have defined a ConcurrentLinkedQueue and looping over it like :
ConcurrentLinkedQueue clq
.forEach((carTask -> {
Now if I delete carTask from the queue. which is an element
in the queue while we are doing a forEach will that lead to any issue ?
One alternative I think of is put the elements to be deleted
in a separate List and once the forEach is over simply delete all
the elements in the Queue from the List.
I am not sure if this alternative approach will work perfectly
Any suggestions or better way to approach this problem ?
This specific example won't result in an error, because this implementation of Queue allows concurrent modifications.
But removing elements from Java collections via the remove method, while you're looping over the elements, will often result in a ConcurrentModificationException. Instead, it's a good habit to use an Iterator and call its remove method:
Collection<String> c = new LinkedList<>();
c.add("foo");
c.add("bar");
for(Iterator<String> it = c.iterator(); it.hasNext(); ) {
String s = it.next();
if(s.equals("foo")) {
it.remove();
}
}
// collection now contains only "bar"
In addition to preventing ConcurrentModificationException, this is preferable because the time complexity of remove for many collections is linear. Since this queue is implemeneted as a linked list, the list must be traversed until the element to be removed is located. With an Iterator, you've already located the element, and can remove it "in place".
What if you locate the element you want to remove, and it's the last element in the queue? Calling remove on that item requires a traversal all the way to the end of the queue again. In addition, it requires a call to equals for every preceding element. You definitely don't want to put the items to be removed into a list, because you'd have the same negative performance characteristics (along with the allocation of another List).
I am relying on list iterators to move through a list of characters. This is a single-threaded program and I use listIterator objects sequentially in 4 different methods. Each method has the same setup:
private void myMethod(ArrayList<Integer> input) {
ListIterator<Integer> i = input.listIterator();
while (i.hasNext()) {
Integer in = i.next();
if (in < 10)
i.remove();
else
i.set(in*in); // because its lucky
}
}
With this pattern, on the second iterator the following Exception is thrown:
java.util.ConcurrentModificationException
However, looking at the javadocs I don't see this Exception in the Exceptions thrown nor do I see a method to close the iterator after I am done. Am I using the listIterator incorrectly? I have to iterate over the same ArrayList multiple times, each time conditionally removing or mutating each element. Maybe there is a better way to iterate over the ArrayList and this use-case is not best solved by a ListIterator.
java docs for ListIterator
This is explained in the ArrayList javadoc, you are modifying the list with remove() and set() while using an Iterator:
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.
It’s hard to give diagnostic for a problem when the shown code clearly isn’t the code that produced the exception, as it doesn’t even compile. The remove method of Iterator doesn’t take arguments and the set method is defined on ListIterator, but your code declares the variable i only as Iterator.
A fixed version
private void myMethod(ArrayList<Integer> input) {
ListIterator<Integer> i = input.listIterator();
while (i.hasNext()) {
Integer in = i.next();
if (in < 10)
i.remove();
else
i.set(in*in);
}
}
would run without problems. The answer to your general question is that each modification invalidates all existing iterators, except the one used to make the modification when you did use an iterator for the modification and not the collection interface directly.
But in your code, there is only one iterator, which is only created and used for this one operation. As long as there is no overlapping use of iterators to the same collection, there is no problem with the invalidation. Iterators existing from previous operations are abandoned anyway and the iterators used in subsequent operations do not exist yet.
Still, it’s easier to use
private void myMethod(ArrayList<Integer> input) {
input.removeIf(in -> in < 10);
input.replaceAll(in -> in*in);
}
instead. Unlike the original code, this does two iterations, but as explained in this answer, removeIf will be actually faster than iterator based removal in those cases, where performance really matters.
But still, the problem persists. The shown code can’t cause a ConcurrentModificationException, so your actual problem is somewhere else and may still be present, regardless of how this one method has been implemented.
I am not knowledgable enough about Java ListIterators to answer the question but it appears I have run into the XY problem here. The problem seems to be better solved with Java Streams to remove the element or map the element into a new ArrayList by exercising a function on each element in the original ArrayList.
private ArrayList<Integer> myMethod(ArrayList<Integer> input) {
ArrayList<Integer> results = input.stream().filter(
in -> (in < 10)).collect(Collectors.toCollection(ArrayList::new));
results = input.stream().map(
in -> in*in).collect(Collectors.toCollection(ArrayList::new));
return results;
}
I was asked in an interview what is the advantage of using iterator over for loop or what is the advantage of using for loop over iterator?
Can any body please answer this?
First of all, there are 2 kinds of for loops, which behave very differently. One uses indices:
for (int i = 0; i < list.size(); i++) {
Thing t = list.get(i);
...
}
This kind of loop isn't always possible. For example, Lists have indices, but Sets don't, because they're unordered collections.
The other one, the foreach loop uses an Iterator behind the scenes:
for (Thing thing : list) {
...
}
This works with every kind of Iterable collection (or array)
And finally, you can use an Iterator, which also works with any Iterable:
for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
Thing t = it.next();
...
}
So you in fact have 3 loops to compare.
You can compare them in different terms: performance, readability, error-proneness, capability.
An Iterator can do things that a foreach loop can't. For example, you can remove elements while you're iterating, if the iterator supports it:
for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
Thing t = it.next();
if (shouldBeDeleted(thing) {
it.remove();
}
}
Lists also offer iterators that can iterate in both directions. A foreach loop only iterates from the beginning to an end.
But an Iterator is more dangerous and less readable. When a foreach loop is all you need, it's the most readable solution. With an iterator, you could do the following, which would be a bug:
for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
System.out.println(it.next().getFoo());
System.out.println(it.next().getBar());
}
A foreach loop doesn't allow for such a bug to happen.
Using indices to access elements is slightly more efficient with collections backed by an array. But if you change your mind and use a LinkedList instead of an ArrayList, suddenly the performance will be awful, because each time you access list.get(i), the linked list will have to loop though all its elements until the ith one. An Iterator (and thus the foreach loop) doesn't have this problem. It always uses the best possible way to iterate through elements of the given collection, because the collection itself has its own Iterator implementation.
My general rule of thumb is: use the foreach loop, unless you really need capabilities of an Iterator. I would only use for loop with indices with arrays, when I need access to the index inside the loop.
Iterator Advantage:
Ability to remove elements from Collections.
Ability to move forward and backward using next() and previous().
Ability to check if there more elements or not by using hasNext().
Loop was designed only to iterate over a Collection, so if you want just to iterate over a Collection, its better to use loop such as for-Each, but if you want more that that you could use Iterator.
The main difference between Iterator and the classic for loop, apart from the obvious one of having or not having access to the index of the item you're iterating, is that using Iterator abstracts the client code from the underlying collection implementation, allow me to elaborate.
When your code uses an iterator, either in this form
for(Item element : myCollection) { ... }
this form
Iterator<Item> iterator = myCollection.iterator();
while(iterator.hasNext()) {
Item element = iterator.next();
...
}
or this form
for(Iterator iterator = myCollection.iterator(); iterator.hasNext(); ) {
Item element = iterator.next();
...
}
What your code is saying is "I don't care about the type of collection and its implementation, I just care that I can iterate through its elements". Which is usually the better approach, since it makes your code more decoupled.
On the other hand, if you're using the classic for loop, as in
for(int i = 0; i < myCollection.size(); i++) {
Item element = myCollection.get(i);
...
}
Your code is saying, I need to know the type of collection, because I need to iterate through its elements in a specific way, I'm also possibly going to check for nulls or compute some result based on the order of iteration. Which makes your code more fragile, because if at any point the type of collection you receive changes, it will impact the way your code works.
Summing it up, the difference is not so much about speed, or memory usage, is more about decoupling your code so that is more flexible to cope with change.
if you access to data by number (e.g. "i"), it is fast when you use array. because it goes to element directly
But, other data structure (e.g. tree, list), it needs more time, because it start from first element to target element. when you use list. It needs time O(n). so, it is to be slow.
if you use iterator, compiler knows that where you are. so It needs O(1)
(because, it start from current position)
finally, if you use only array or data structure that support direct access(e.g. arraylist at java). "a[i]" is good. but, when you use other data structure, iterator is more efficient
Unlike other answers, I want to point another things;
if you need to perform the iteration in more than one place in your code, you will likely end up duplicating the logic. This clearly isn’t a very extensible approach. Instead, what’s needed is a way to separate the logic for selecting the data from the code that actually processes it.
An iterator solves these problems by providing a generic interface for looping over a set of data so that the underlying data structure or storage mechanism — such as an array- is hidden.
Iterator is a concept not an implementation.
An iterator provides a number of operations for traversing and accessing data.
An iterator may wrap any datastructure like array.
One of the more interesting and useful advantages of using iterators is the capability to wrap or decorate another iterator to filter the return values
An iterator may be thread safe while a for loop alone cannot be as it is accessing elements directly. The only popular thread-safety iterator is CopyOnWriteArrayList but it is well known and used often so worth mentioning.
This is from the book that it is https://www.amazon.com/Beginning-Algorithms-Simon-Harris/dp/0764596748
I stumbled on this question. The answer lies to the problems Iterator tries to solve:
access and traverse the elements of an aggregate object without exposing its representation
define traversal operations for an aggregate object without changing its interface
I'm getting a ConcurrentModificationException despite using the iterator to perform the remove operation. Any ideas as to why?
for (Iterator<Thread> iter = threads.iterator(); iter.hasNext();) {
Thread hook = iter.next();
if(someCondition){
iter.remove();
}
}
From JavaDoc Iterator.remove():
Removes from the underlying collection the last element returned by
the iterator (optional operation). This method can be called only once
per call to next. The behavior of an iterator is unspecified if the
underlying collection is modified while the iteration is in progress
in any way other than by calling this method.
It seem that the behavior is depended to the collection. Also as aioobe pointed out. I can reproduce ConcurrentModificationException when I modify the collection somewhere else. Using only Iterator interface, I can only reproduce IllegalStateException.
Because you have a modification concurrent to using an Iterator, which is not supported. Either iterate a list clone, or use a CopyOnWriteArrayList.
Or memory what to remove in a new list, and call list.removeAll(whatIWantedToRemove) afterwards.
Is there a method in JDK or apache commons to "pop" a list of elements from a java.util.List? I mean, remove the list of elements and return it, like this method:
public Collection pop(Collection elementsToPop, Collection elements) {
Collection popped = new ArrayList();
for (Object object : elementsToPop) {
if (elements.contains(object)) {
elements.remove(object);
popped.add(object);
}
}
return popped;
}
If you're looking for a stack-like structure I suggest accepting a Deque (LinkedList is the most common implementation) instead of a Collection.
If you don't actually need to treat it as a stack, just get an iterator from the Collection and use the remove() method:
for (Iterator<SomeType> it = elements.iterator(); it.hasNext(); ) {
SomeType e = it.next();
it.remove();
popped.add(e);
}
Do note that remove is an optional operation, and some implementations may throw an UnsupportedOperationException (for example, the iterator returned by a Collection from Collections.unmodifiable...() will).
Edit: After looking more closely at your question, I think you just need this:
elements.removeAll(elementsToRemove);
If your main point is you need to know exactly which elements were actually popped, I think you're stuck with your original code.
There is no such method in the standard JDK-provided methods. Apache Commons provides the ListUtils.subtract() method.
Edit: As other answerers have noted, your use of the term pop is nonstandard. Usually,
The pop operation removes an item from the top of [a stack]
Wikipedia has a nice description of stacks.
I guess no, because you definition of 'pop' operation is highly non-standard. Usually it takes no arguments (except collection itself) and returns and removes the top-most one.
But once you noted apache commons, this would achieve the same effect as your code.
Collection result = CollectionUtils.intersection(a, b);
a.removeAll(b);
edit
http://commons.apache.org/collections/api-release/index.html
Linked List provides the functionality as you require, provides a push and pop method.
Refer to the documentation as provided:
There isn't a method exactly like what you are asking for, but it looks like you are already pretty close with your code.
Some suggestions:
Consider using removeAll(object) instead of remove(object) if elements is an arbitrary collection since you may need to remove duplicates e.g. if elements is a list.
contains() is slow for some collection types (e.g. lists) since it needs to traverse the entire data structure. Given that this is in your inner loop you are at risk of O(n^2) performance issues. If you can make the algorithm work with a HashSet or HashMap then contains() will by O(1) and your algorithm will be much more efficient.