I'm working on a project for school but i'm a little stuck right now
My problem is that i have an arrayList of Squares
Each Square has a value(from 0 to 100). Its starting value is 9999 so i can check if its is checked.
If a square is checked i want it to be removed from the arrayList.
So after a while there will be no Squares left.
there is a little bit of code where the first value is set so thats why i check if the value is 9999.
But i get an error. One that i havent seen before.
Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException
Vak = Square
this is my code:
while (!vakken.isEmpty()) { // check if empty
Iterator itrVak = vakken.iterator();
while (itrVak.hasNext()) {
Vak vak = (Vak) itrVak.next(); // here is get the error
if (vak.getValue() != 9999) {// check if square value is 9999
Collection checkVakken = vak.getNeighbour().values();
Iterator itre = checkVakken.iterator();
while (itre.hasNext()) {
Vak nextVak = (Vak) itre.next();
if (nextVak != null) {
if (nextVak.getValue() == 9999) {
nextVak.setValue(vak.getValue() + 1); // set value by its neighbour
vakken.remove(vak);
checkvakken.add(vak);
}
}
}
} else {
vakken.remove(vak);
checkvakken.add(vak);
}
}
}
You are removing elements from the collection while you are iterating it. As the iterator may produce unpredictable results in this situation, it fails fast throwing the exception you encountered.
You may only alter a collection through the iterator's methods while traversing it. There should be remove method on the iterator itself, that removes the current element and keeps the iterator intact.
While iterating, you should use Iterator instance for removing object:
itre.remove();
You can try like this:
itre.remove();
ITERATOR never lets you modify when you are iterating.. you need to use loops instead.. this happens coz you are using the Iterator, same time other thread is modifying the list...
Related
In the code below I have a try catch block that attempts to remove an element from a Vector, using Iterator. I've created my own class QueueExtendingVect that extends Vector and implements Iterator.
The variable qev1 is an instance of class QueueExtendingVect. I've already added a few elements to this Vector as well.
try
{
qev1.iterator().remove();
}
catch(UnsupportedOperationException e)
{
System.out.println("Calling Iterator.remove() and throwing exception.");
}
qev1.enqueue(ci);
qev2.enqueue(ci);
qcv1.enqueue(ci);
qcv2.enqueue(ci);
for (int i = 1; i < 5; i++)
{
if (i % 2 == 0)
{
qev1.enqueue(new CInteger(i+1));
qev2.enqueue(new CInteger(i+1));
qcv1.enqueue(new CInteger(i+1));
qcv2.enqueue(new CInteger(i+1));
}
else
{
qev1.enqueue(new Date(i*i));
qev2.enqueue(new Date(i*i));
qcv1.enqueue(new Date(i*i));
qcv2.enqueue(new Date(i*i));
}
}
In this code I add a few elements to the Vector qev1. The other variables are in other parts of the code.
However, when I run my program I get an IllegalStateException at runtime. I'm not sure what this means.
You haven't called next() on your Iterator, so it's not referring to the first item yet. You can't remove the item that isn't specified yet.
Call next() to advance to the first item first, then call remove().
#rgettman answer is correct but to give you imagination.
Our collection: |el1| |el2| |el3|
when you call iterator.next() it works this way:
|el1| iterator |el2| |el3|
so it jumps over the element and return reference to the element which was jumped (|el1|). So if we called iterator.remove() now, |el1| would be removed.
It's worth to add what #PedroBarros mentioned above - you can't call iterator.remove() two times without iterator.next() between them because IllegalStateException would be thrown.
Also when you create two iterators (iterator1, iterator2) then calling:
iterator1.next();
iterator1.remove();
iterator2.next();
will throw ConcurrentModificationException because iterator2 checks that collection was modified.
It will also call this exeption, If you add something to the list in iterator and then after it not calling it.next() again but removing the item
[For clarification, 'monsters' is a list of NPCs that when shot by an object 'bullet' are removed from the list. ]
Error at start:
W/System.err: java.util.ConcurrentModificationException
W/System.err: at java.util.ArrayList$Itr.next(ArrayList.java:831)
W/System.err: at com.companyname.product.GameplayScene.update(GameplayScene.java:113)
//...
I believe this means that it is trying to perform an action on something in the list that isn't there. So my question is could I please get some help identifying the point where an object is being called that isn't there, as I can't seem to find it. I know which class it is in as the first line references it for each error.
for (Bullet bullet : player.getList())
if (npcManager.bulletCollide(bullet)) { //checks for a collision between all npcs and all bullets
player.getList().remove(bullet);//npc is removed in method above
}
if (!gameOver) {
npcManager.update(); //updates movement of npcs
if (npcManager.playerCollideNPC(player)) {
//end game
}
}
for (RectNPC NPC : npcManager.getList())
if (obstacleManager.NPCCollide(NPC)) { //checks collision between npcs and other objects
//
}
int i = 0;
//checks collisions between NPCs themselves
while (i < (Constants.NUMBER_ENEMIES - 1)) {
if (npcManager.getList().size() <= 1)
return;
if (Rect.intersects(npcManager.getList().get(i).getRectangle(), npcManager.getList().get(i + 1).getRectangle()))
npcManager.getList().get(i).setRectangle(200);
i += 1;
}
}
(Above) I imagine the issue will be with calling something in the update (shown above) where the object is no longer available, is there an issue with any of how I am removing the NPCs?
public boolean bulletCollide(Bullet bullet) {
for(RectNPC npc : monsters) {
if(npc.bulletCollideNPC(bullet)) {
monsters.remove(npc);
monsters.add(0, new RectNPC(new Rect(100, 100, 200, 200), Color.rgb(255, 0, 0), 25));
return true;
}
}
return false;
}
(Above) Code where I am removing the NPC, I've included incase it is helpful - however it does do what it's meant to so I don't believe this is the problem.
My main question is, is there anything here that would be causing this error (the game stopping for a few frames and giving the error at the top) - or is there something/somewhere else in specific I should be looking at? Also I know some of my syntax isn't great, I apologise it's my first Java project.
Current Iterators:
for(Iterator<RectNPC> iterator = monsters.iterator(); iterator.hasNext();) {
if(iterator.next().bulletCollideNPC(bullet)) {
iterator.remove();
monsters.add(0, new RectNPC(new Rect(100, 100, 200, 200), Color.rgb(255, 0, 0), 25));
return true;
}
}
and
for (Iterator<Bullet> iterator = player.getList().iterator(); iterator.hasNext(); ) {
if (npcManager.bulletCollide(iterator.next())) {
iterator.remove();
//
}
}
In java, you cannot do for( T variable : collection ) { collection.remove( variable ); } In other words, you cannot be removing items from a collection which is being iterated with a for loop. It will result in a ConcurrentModificationException. Google for "java fail-fast iterator" for more information about why and how.
You have two options:
Collect in a temporary list all the monsters that are to be removed, then once you are done iterating over the main list, iterate once more through the temporary list to remove them from the main list. The point is that you are not going to be removing from the same list that you are iterating.
Instead of a "foreach" (for) loop, use an actual iterator, and when you want to remove an item, remove it by invoking the iterator's remove() method, not the containing collection's remove() method. The iterator's remove() method does the necessary tricks to prevent a ConcurrentModificationException from being thrown.
Use Iterator for a safe way to remove your Elements.
Note that Iterator.remove is the only safe way to modify a collection
during iteration; the behavior is unspecified if the underlying
collection is modified in any other way while the iteration is in
progress.
From Java SE documentation
static void filter(Collection<?> c) {
for (Iterator<?> it = c.iterator(); it.hasNext(); )
if (!cond(it.next()))
it.remove();
}
Example
Your method is doing 3 different things. It's returning a boolean, removing an element from a list, and then adding an element. I would restructure the code so that you have 3 methods that do only 1 thing.
You can use the power of Java 8's internal iterator, as a starting point
monsters.removeIf(e -> e.bulletCollideNPC(bullet));
I'm having issues with getting an iteration done (and modification) through the Set, which contains Objects. I've tried so many ways of iteration (4), but none of them seem to work and still throw me the Error java.util.ConcurrentModificationException.
[Code is written in Groovy]
private void replaceRock() {
ObjectNodeManager.OBJECTS.each {
System.out.println("Going...");
if(it.getPosition().withinDistance(player.getPosition(), 30)) {
System.out.println("Found...");
Position position = it.getPosition();
ObjectNode newRock = new ObjectNode(439, position, ObjectDirection.NORTH, ObjectType.DEFAULT);
ObjectNodeManager.unregister(it);
ObjectNodeManager.register(newRock);
it.remove();
}
}
}
I've tried synchronization to prevent access from other Threads, but this also didn't work. Please help me, I'm very desperate.
First find them (this will give you basically a list of refs) and then deal with them:
ObjectNodeManager.OBJECTS.findAll {
it.getPosition().withinDistance(player.getPosition(), 30))
}.each{
ObjectNode newRock = new ObjectNode(439, it.position, ObjectDirection.NORTH, ObjectType.DEFAULT)
ObjectNodeManager.unregister(it)
ObjectNodeManager.register(newRock)
it.remove()
}
On a random site note: i'd add a replace method in the ObjectNodeManager to combine unregister, register, remove. Also working with class methods and properties is not the best thing to do (but since it looks like a game...)
The problem is that you are modifying the list of objects while you are looping through the objects.
Try iterating through a copy of the objects instead.
ArrayList<YourType> copy = new ArrayList<YourType>(ObjectNodeManager.OBJECTS);
copy.each(...)
In the code below I have a try catch block that attempts to remove an element from a Vector, using Iterator. I've created my own class QueueExtendingVect that extends Vector and implements Iterator.
The variable qev1 is an instance of class QueueExtendingVect. I've already added a few elements to this Vector as well.
try
{
qev1.iterator().remove();
}
catch(UnsupportedOperationException e)
{
System.out.println("Calling Iterator.remove() and throwing exception.");
}
qev1.enqueue(ci);
qev2.enqueue(ci);
qcv1.enqueue(ci);
qcv2.enqueue(ci);
for (int i = 1; i < 5; i++)
{
if (i % 2 == 0)
{
qev1.enqueue(new CInteger(i+1));
qev2.enqueue(new CInteger(i+1));
qcv1.enqueue(new CInteger(i+1));
qcv2.enqueue(new CInteger(i+1));
}
else
{
qev1.enqueue(new Date(i*i));
qev2.enqueue(new Date(i*i));
qcv1.enqueue(new Date(i*i));
qcv2.enqueue(new Date(i*i));
}
}
In this code I add a few elements to the Vector qev1. The other variables are in other parts of the code.
However, when I run my program I get an IllegalStateException at runtime. I'm not sure what this means.
You haven't called next() on your Iterator, so it's not referring to the first item yet. You can't remove the item that isn't specified yet.
Call next() to advance to the first item first, then call remove().
#rgettman answer is correct but to give you imagination.
Our collection: |el1| |el2| |el3|
when you call iterator.next() it works this way:
|el1| iterator |el2| |el3|
so it jumps over the element and return reference to the element which was jumped (|el1|). So if we called iterator.remove() now, |el1| would be removed.
It's worth to add what #PedroBarros mentioned above - you can't call iterator.remove() two times without iterator.next() between them because IllegalStateException would be thrown.
Also when you create two iterators (iterator1, iterator2) then calling:
iterator1.next();
iterator1.remove();
iterator2.next();
will throw ConcurrentModificationException because iterator2 checks that collection was modified.
It will also call this exeption, If you add something to the list in iterator and then after it not calling it.next() again but removing the item
public void putExpensiveWineCaseBack(double notBiggerThan)
{
Iterator<WineCase> it = basket.iterator();
WineCase checkedWineCase = null;
while( it.hasNext() )
{
checkedWineCase = it.next();
double checkedPrice = checkedWineCase.getPrice();
int i=0;
for(i=0; i<basket.size(); i++)
{
if(checkedPrice > notBiggerThan)
{
basket.remove(i);
}
}
}
}
}
This code is compiling. The problem is that when executed I get this error:
java.util.ConcurentModificationexception:
null(in java.util.ArrayList$Itr)
for this line:
checkedWineCase = it.next();
What am I missing ?
Change from
basket.remove(i);
to
it.remove();
You're calling basket.remove() but should call it.remove() instead.
You are removing items from the list in the loop where you are iterating through the items in the list. That is the cause of the ConcurrentModificationException.
'null pointer' does not exactly describe your problem, rather it is the name of the exception you received: ConcurentModificationexception
When an iterator is instantiated, it provides access to a certain group of objects, in this case, the contents of 'basket'. It might take some time to go from getting the first object in the iterator to getting the last one.
Now, what happens if the objects in the 'basket' change? The iterator is designed to be 'fail-fast', meaning if the basket has changed, you will immediately get an exception the next time you try to use the Iterator.
This is happening because in some cases you call 'basket.remove()' before you have finished iterating over everything in the basket. You may wish to 'remember' which things should be removed from the basket, and then remove them only when you are completely done with the iterator.
Google 'java iterator concurrentmodificationexception' to see many more explanations of the issue you are encountering.
The problem is you are removing elements from basket while you are iterating over it.
Actually I'm not sure what you are trying to do, as that for loop makes not much sense to me. But I guess you want to remove the element from the Set if the price is larger than notBiggerThan.
So maybe you should try like this:
while(it.hasNext()) {
checkedWineCase = it.next();
double checkedPrice = checkedWineCase.getPrice();
if(checkedPrice > notBiggerThan)
{
it.remove();
}
}
You should not modify the collection while iterating, except by way of Iterator.remove().
The problem comes from your call to basket.remove(i);
I do not completely understand what you are trying to do with that inner for loop (currently it looks like it will remove everything from your basket if any have a price > than the maximum), maybe you want the following:
public void putExpensiveWineCaseBack(double notBiggerThan)
{
Iterator<WineCase> it = basket.iterator();
WineCase checkedWineCase = null;
while( it.hasNext() )
{
checkedWineCase = it.next();
double checkedPrice = checkedWineCase.getPrice();
if(checkedPrice > notBiggerThan)
{
it.remove();
}
}
}