This is my code:
Iterator it = queue.iterator();
while(it.hasNext()){
random = randNumber(1,2);
if(random == 1){
queue.poll();
} else {
queue.add("new");
queue.poll();
}
}
It gives me:
Exception in thread "test" java.util.ConcurrentModificationException
at java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:761)
at java.util.LinkedList$ListItr.next(LinkedList.java:696)
Edit #Jon Skeet:
What I want to do is:
I have a queue list in, let say the size is 10, lets say: a,b,c,d ... j
Generate a number between 1 and 2. if 1, pull (remove the top element) else if 2 add new element
I will stop the loop until I added 3 new elements
In general, you can't modify collections while you're iterating over them. One alternative is to build a separate list of "changes" you want to apply, and then apply them once you've finished iterating.
Alternatively, some collections do support this such as ConcurrentLinkedQueue - but most offer no guarantees about whether the iterator will see the changes made while you're iterating. (I suspect that's mainly because they're also thread-safe, but I've rarely seen documented guarantees about what will happen if you modify the collection within the iterating thread.)
EDIT: I'm not sure that an iterator is the right approach here. Instead, you could use:
while (!queue.isEmpty())
{
// Put logic in here - add, poll etc
}
One thing to note is that your posted code doesn't actually move the iterator forward at any time - it never calls it.next(). That's a strong suggestion that either you're not using the iterator fully, or you don't need it at all.
Is this really copy-pasted your code?
What I can think is that You confirmed that q and queue are references to the same queue-object.
So you cannot modify any type of list, queue, stack when iterating over it. To avoid iteration, you can try a for(int i = 0; ..... ; i++) loop. But this isn't a good idea. Because you are changing size when you are using the size to check if you are at the end of the loop.
I read your edit:
for (int i = 0; i < 3;)
{
boolean b = Math.random() < 0.5d;
if (b)
{
queue.poll();
} else {
queue.add("new"); // or put(), I don't know exectly
i++;
}
}
If 'queue' is a List, you can use ListIterator
excerpt:
An iterator for lists that allows the programmer to traverse the list in either direction, modify the list during iteration, and obtain the iterator's current position in the list.
You should use ListIterator. It has .remove() and .set() methods that will allow you to modify the underlying collection without hosing the iterator's state.
In general, modifying the collection in any other way is going to hose the iterator's state--be glad it threw an exception and didn't do something more insidious.
Related
occupants is an java.util.ArrayList.
I am iterating through it like so
public void hitOccupants(SnakeController snakeController){
ListIterator<Hitable> i = occupants.listIterator();
while( i.hasNext()){
Hitable hitable = i.next();
if(hitable.hit(snakeController)){//returns true if it should be deleted
i.remove();
}
}
}
I can figure out why this would give a ConcurrenModificationException...
I am using libgdx, so there could be a threading issue. This is my first libgdx project though, so I am not sure. Running the code on android. Stacktrace:
java.util.ConcurrentModificationException
at java.util.AbstractList$SimpleListIterator.remove(AbstractList.java:71)
at com.ninovanhooff.snake.model.BoardSpace.hitOccupants(BoardSpace.java:65)
at com.ninovanhooff.snake.controller.SnakeController.act(SnakeController.java:77)
at com.ninovanhooff.snake.controller.BoardController.act(BoardController.java:72)
at com.ninovanhooff.snake.GameActor$2.act(GameActor.java:77)
at com.badlogic.gdx.scenes.scene2d.Actor.act(Actor.java:86)
at com.badlogic.gdx.scenes.scene2d.Group.act(Group.java:48)
at com.badlogic.gdx.scenes.scene2d.Group.act(Group.java:48)
at com.badlogic.gdx.scenes.scene2d.Stage.act(Stage.java:225)
at com.ninovanhooff.snake.SnakeGame.render(SnakeGame.java:66)
at com.badlogic.gdx.backends.android.AndroidGraphics.onDrawFrame(AndroidGraphics.java:510)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1516)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
ConcurrentModificationException as per java docs
This exception may be thrown by methods that have detected concurrent
modification of an object when such modification is not permissible.
For example, it is not generally permissible for one thread to modify
a Collection while another thread is iterating over it. In general,
the results of the iteration are undefined under these circumstances.
Some Iterator implementations (including those of all the general
purpose collection implementations provided by the JRE) may choose to
throw this exception if this behavior is detected. Iterators that do
this are known as fail-fast iterators, as they fail quickly and
cleanly, rather that risking arbitrary, non-deterministic behavior at
an undetermined time in the future.
In short one cannot modify list while iterating through it .
There are multiple ways :
1) Create a new list
2) Use of different collections such as Map or Set.
3) Change some state in hitable object
Hitable.hit() adds an element to the array, thus causing concurrent modification.
To place this into context:
I am making the classic snake game. When the snake hits the Hitable apple:
1) The apple has to be removed from the BoardSpace's occupants //BoardSpace == tile
this is done in the code discussed here
2) The snakeÅ› body is elongated into the BoardSpace where the apple was. The snake is now an occupant of the BoardSpace, thus the snake is added to occupants.
Both these are done inside Apple.hit(), ergo: concurrent modification.
Solution: I used a CopyOnWriteArrayList to trave occupants in the original order and contents, and added the elements to be removed for later removal.
CopyOnWriteArrayList<Hitable> occupantsSnapshot = new CopyOnWriteArrayList<Hitable>(occupants);
ArrayList<Hitable> removals = new ArrayList<Hitable>();
Iterator<Hitable> i = occupantsSnapshot.iterator();
while (i.hasNext()) {
Hitable hitable = i.next();
boolean remove = hitable.hit(snakeController);
if (remove) {//returns true if it should be deleted
removals.add(hitable);
}
}
for(Hitable hitable: removals){
occupants.remove(hitable);
boardController.removeHitable(hitable);
}
For educational purposes: Bitbucket snapshot
See AppleController and SnakeBodyParts.
You're not allowed to remove items from an ArrayList while iterating through it. This is done for a number of reasons. Most obviously, an ArrayList is dynamic, so if you remove the object at index 2, the object at index 3 now shifts down to index 2. This matters because, while iterating, it could easily lead to an out-of-bounds exception if you were to shorten the length of the list without re-adjusting your iterator.
There are a number of ways to get around this, but there's a standing rule: if you're iterating, you can't remove. So either think of a way to do it without iterating (a while loop that only increments the index when hitable.hit is false) or store the objects to be removed in a separate list and then remove those items one by one.
This question already has answers here:
Do we ever need to use Iterators on ArrayList?
(6 answers)
Closed 9 years ago.
I was reading the answer mentioned to the question
"Do we ever need to use Iterators on ArrayList?".
In the answer, the user stated something like this: "A big use case of iterators with ArrayLists is when you want to remove elements while iterating".
This could be achieved even using remove method of ArrayList in Java. My question is why we need iterator in ArrayList?
Consider the code:
import java.util.*;
public class ocajp66 {
public static void main(String[] args) {
ArrayList a = new ArrayList();
for (int i = 0; i < 10; i++) {
a.add(i);
}
System.out.printf("BEFORE ITERATOR\n");
for (int i = 0; i < a.size(); i++) {
System.out.printf("I:%d\n", a.get(i));
}
System.out.printf("AFTER ITERATOR\n");
Iterator i = a.iterator();
while (i.hasNext()) {
System.out.printf("I:%d\n", i.next());
}
}
}
Can anybody explain the significance of the iterator? It would be wonderful if you could explain me with code.
As you have stated iterator is used when you want to remove stuff whilst you iterate over the array contents. If you don't use an iterator but simply have a for loop and inside it use the remove method you will get exceptions because the contents of the array changes while you iterate through. e.g: you might think array size is 10 at the start of the for loop but it wont be the case once you remove stuff.. so when u reach the last loops probably there will be IndexOutofBoundsException etc.
It is clear that an ArrayList-like API could work without the iterator() method. However, an ArrayList is a Collection and the iterator() method is defined in the Collection interface ... so ArrayList has to implement it.
The point about deleting from an ArrayList is that doing it by indexing requires some thought:
for (int i = 0;
i < a.size(); // Hoist this at your peril
i++) {
if (a.get(i) == something) {
a.remove(i);
i--; // Leave this out at your peril
}
}
And it gets worse if you need to remove the list element in a method called from the loop ... 'cos the method has to then say that it has removed an element so that the caller can adjust the loop index.
A third reason why iterator is a good thing on an ArrayList is that it allows you to use Java 5's for (type var : iterable) ... syntax.
The bottom line is that you don't have to use iterators on ArrayList instances. If you don't want to, then don't.
This is an example of how it is possible to get the results you want in several different ways. This kind of redundancy is not unique to Java.
for (int i=0; i < myArray.length; i++) { ... }
This syntax was introduced in the very early versions of Java. It iterates over a usual Java array in a for { } loop. This is generally safe because Java arrays are fixed length and so "Index Out of Bounds" exceptions are not possible.
for (int i=0; i < myArrayList.size(); i++ { ... }
This syntax reflects a later release of Java, after the introduction of the Collections API which introduced ArrayList. Classes that implement the Collection interface, as already mentioned above, must implement an Iterator but you don't have to use it. This for { } loop doesn't, but the danger here is that ArrayLists are not fixed size. If it should shrink in the body of your for loop, and exception can result.
for (MyArrayType t : myArrayList) { }
This syntax was also released in a later release of Java. It is called the enhanced for loop. Any collection class that provides an Iterator by implementing the Iterable interface can take advantage of this syntax. This allows iterating over items in a collection without having to explicitly instantiate an Iterator. A favorite way to use this in a JavaFX Application is to loop through a bunch of controls to set a property to a value, eg. to reset the contents of a group of TextFields:
for (TextField tf : new TextField[] { txtf1, txtf2, txtf3, txtfa, txtfb, txtfc}) {
tf.setText("");
}
while (myCollectionIterator.hasNext()) { }
You can always explicitly instantiate an Iterator. This is safe to use when collection size is changing (from the Collection's own methods). It correct to say that the Iterator is more closely a property of the Iterable interface than a feature of the core Java language. But you can still use it as a language-like feature (in the enhanced for loop) thanks to later Java releases.
These constructs provide redundancy, but they are not identical. There are nuances of each that enable one to be particularly useful at a given time. You should use all of them.
Q: Why do we need an iterator in ArrayList?
We don't - just as you've shown in your code, you can iterate and do core operations on an ArrayList without an iterator. But it's a nice to have feature.
Q: Can anybody explain the significance of the iterator?
In addition to its design value, one I could see is its fail-fast feature. I quote this paragraph from the ArrayList documentation:
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.
You were looking for code, you can actually see the ArrayList's iterator implementation here: ArrayList.java.
For your question, if we use list.remove() method instead of iterator.remove() then IndexOutOfBoundsException will be thrown.
list.remove() is safe to use if you put break statement once you find specific object/index to be removed so that it will be exited from the loop without any Exception(like IndexOutOfBoundsException )
Following iterator code still can throw ConcurrentModificationException if we use iterator EVEN in synchronized environment.
List<String> empNames = new ArrayList<String>();
synchronized (empNames) {
Iterator<String> iterator = empNames.iterator();
while (iterator.hasNext()) {
iterator.next();
empNames.add("Another Name"); // throws
// ConcurrentModificationException
}
}
The following function walks recursively through a list and divide it always by half and do something with the sublists. The recursion breaks when the listsize is 2. I know a concurrent modification exception occurs if I change the list when I iterate over it. But I don't use iterations and it still happens:
private static List<ParticipantSlot> divide(List<ParticipantSlot> list) {
int n = list.size();
//do something
if (n>2){
List<ParticipantSlot> l = divide(list.subList(0, n/2-1));
List<ParticipantSlot> r= divide(list.subList(n/2, n));
l.addAll(r);
return l;
}else{
return list;
}
}
You're using addAll() which will iterate over the collection you provide in the argument. Now subList only returns a view onto the original list, so you're trying to add values onto a view of the original list, and iterate over a different part of the original list at the same time. Bang.
If you created a copy of the sublist each time, it should work - although it'll be pretty inefficient.
You get a concurrent modification exception because sublist is backed by the original list:
The returned list is backed by this list, so non-structural changes in the returned list are reflected in this list, and vice-versa. The returned list supports all of the optional list operations supported by this list.
If you would like to avoid an exception, make a copy of the first sublist before modifying it.
If you are using ArrayList, you may want to change it to a CopyOnWriteArrayList, or ConcurrentLinkedQueue.
If you are on a Multi-thread environment, you will want to put a synchronized around your Array.
Hope it helps.
I use HashSet for add(); remove(); clear(); iterator(); methods. So far everything worked like a charm. However, now I need to fulfill a different requirement.
I'd like to be able to start iterating from a certain index. For example, I'd like the following two programs to have same output.
Program 1
Iterator it=map.iterator();
for(int i=0;i<100;i++)
{
it.next();
}
while (it.hasNext())
{
doSomethingWith(it.next());
}
Program 2
Iterator it=map.iterator(100);
while (it.hasNext())
{
doSomethingWith(it.next());
}
The reason I don't want to use the Program 1 is that it creates unnecessary overhead. From my research, I couldn't not find a practical way of creating an iterator with beginning index.
So, my question is, what would be a good way to achieve my goal while minimizing the overhead?
Thank you.
There is a reason why add(), remove(), are fast in a HashSet. You are trading the ability to treat the elements in the set as a random access list for speed and memory costs.
I'm afraid you can't really do that unless you convert your Set into a List first. This is simple to do but it usually involved a complete processing of all the elements in a Set. If you want the ability to start the iterator from a certain place more than once form the same state it might make sense. If not then you will probably be better with your current approach.
And now for the code (assuming that Set<Integer> set = new HashSet<Integer>(); is your declared data structure:
List<Integer> list = new ArrayList<Integer>(set);
list.subList(100, list.size()).iterator(); // this will get your iterator.
HashSet does not have order. So you could put the set into a List which could use index.
Example:
HashSet set = new HashSet();
//......
ArrayList list = new ArrayList(set);
Since a HashSet's iterator produces items in no particular order, it doesn't really make any difference whether you drop 100 items from the beginning or from the end.
Dropping items from the end would be faster.
Iterator it = map.iterator();
int n = map.size() - 100;
for (int i = 0; i < n; i++)
doSomethingWith(it.next());
You can make use of a NavigableMap. If you can rely on keys (and start from a certain key), that's out of the box.
Map<K,V> submap = navigableMap.tailMap(fromKey);
Then you'll use the resulting submap to simply get the iterator() and do your stuff.
Otherwise, if you must start at some index, you may need make use of a temporary list.
K fromKey = new ArrayList<K>( navigableMap.keySet() ).get(index);
and then get the submap as above.
Following #toader's suggestion.
for(Integer i : new ArrayList<Integer>(set).subList(100, set.size())) {
// from the 100'th value.
}
Note: the nth value has no meaning with a HashSet. Perhaps you need a SortedSet in which case the 100th would be 100th largest value.
Though for-each loop has many advantages but the problem is ,it doesn't work when you want to Filter(Filtering means removing element from List) a List,Can you please any replacement as even traversing through Index is not a good option..
What do you mean by "filtering"? Removing certain elements from a list? If so, you can use an iterator:
for(Iterator<MyElement> it = list.iterator(); it.hasNext(); ) {
MyElement element = it.next();
if (some condition) {
it.remove();
}
}
Update (based on comments):
Consider the following example to illustrate how iterator works. Let's say we have a list that contains 'A's and 'B's:
A A B B A
We want to remove all those pesky Bs. So, using the above loop, the code will work as follows:
hasNext()? Yes. next(). element points to 1st A.
hasNext()? Yes. next(). element points to 2nd A.
hasNext()? Yes. next(). element points to 1st B. remove(). iterator counter does NOT change, it still points to a place where B was (technically that's not entirely correct but logically that's how it works). If you were to call remove() again now, you'd get an exception (because list element is no longer there).
hasNext()? Yes. next(). element points to 2nd B. The rest is the same as #3
hasNext()? Yes. next(). element points to 3rd A.
hasNext()? No, we're done. List now has 3 elements.
Update #2: remove() operation is indeed optional on iterator - but only because it is optional on an underlying collection. The bottom line here is - if your collection supports it (and all collections in Java Collection Framework do), so will the iterator. If your collection doesn't support it, you're out of luck anyway.
ChssPly76's answer is the right approach here - but I'm intrigued as to your thinking behind "traversing through index is not a good option". In many cases - the common case in particular being that of an ArrayList - it's extremely efficient. (In fact, in the arraylist case, I believe that repeated calls to get(i++) are marginally faster than using an Iterator, though nowhere near enough to sacrifice readability).
Broadly speaking, if the object in question implements java.util.RandomAccess, then accessing sequential elements via an index should be roughly the same speed as using an Iterator. If it doesn't (e.g. LinkedList would be a good counterexample) then you're right; but don't dismiss the option out of hand.
I have had success using the
filter(java.util.Collection collection, Predicate predicate)
method of CollectionUtils in commons collections.
http://commons.apache.org/collections/api-2.1.1/org/apache/commons/collections/CollectionUtils.html#filter(java.util.Collection,%20org.apache.commons.collections.Predicate)
If you, like me, don't like modifying a collection while iterating through it's elements or if the iterator just doesn't provide an implementation for remove, you can use a temporary collection to just collect the elements you want to delete. Yes, yes, its less efficient compared to modifying the iterator, but to me it's clearer to understand whats happening:
List<Object> data = getListFromSomewhere();
List<Object> filter = new ArrayList<Object>();
// create Filter
for (Object item: data) {
if (throwAway(item)) {
filter.add(item);
}
}
// use Filter
for (Object item:filter) {
data.remove(item);
}
filter.clear();
filter = null;