A strange ConcurrentModificationException on iteration - java

this
is probably the closest case to mine, but that didn't help either.
I'm getting the ConcurrentModificationException here:
for (Iterator<ProjectileBase> iterator = projectiles.iterator(); iterator.hasNext();) {
ProjectileBase proj = iterator.next(); < here
if (proj == null || !proj.isValid()) {
iterator.remove();
continue;
}
if (((!proj.ignoreRange()) ? proj.lived <= proj.data.getRange() : true)){
proj.lived++;
proj.onTick();
} else {
MissileHitEvent event = new MissileHitEvent(proj.shooter, proj.wand, proj, false, null);
Bukkit.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
iterator.remove();
continue;
} else {
proj.lived = 0;
}
}
}
Even though I did as suggested here
?
The list is specified like this:
private List<ProjectileBase> projectiles = new ArrayList<ProjectileBase>();
which is intialized on the class construction. What's the problem?
EDIT: console log:
[10:01:58] [Craft Scheduler Thread - 3754/WARN]: Exception in thread "Craft Scheduler Thread - 3754"
[10:01:58] [Craft Scheduler Thread - 3754/WARN]: org.apache.commons.lang.UnhandledException: Plugin MagicWands v1.0 generated an exception while executing task 247
at org.bukkit.craftbukkit.v1_9_R2.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:57)
at com.destroystokyo.paper.ServerSchedulerReportingWrapper.run(ServerSchedulerReportingWrapper.java:22)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at io.jettymc.DataHolders.ProjectileManager.iterate(ProjectileManager.java:117)
at io.jettymc.DataHolders.ProjectileManager$1.run(ProjectileManager.java:232)
at org.bukkit.craftbukkit.v1_9_R2.scheduler.CraftTask.run(CraftTask.java:58)
at org.bukkit.craftbukkit.v1_9_R2.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:53)
... 4 more
EDIT 2: Well, I guess it's worth telling, I'm building this project on Bukkit/Spigot (Minecraft server & API).. but I doubt it's the cause of this error?

To help narrow down the problem, there is a trick that might help.
Assuming projectiles is the only reference to the ArrayList, you can temporarily replace it with an immutable list, while you're iterating, so only the Iterator can modify the list. If some other code tries to modify the list, an exception will occur, which should let you know where it happens, assuming your error handling is not messed up.
Example:
List<ProjectileBase> projectilesHold = projectiles;
projectiles = Collections.unmodifiableList(projectiles);
try {
for (Iterator<ProjectileBase> iterator = projectilesHold.iterator(); iterator.hasNext();) {
// other code here is unchanged
}
} finally {
projectiles = projectilesHold;
}
The code saves the modifiable list in the "hold" variable, then wraps the list to make it unmodifiable. The finally block will ensure that the modifiable list is restored, no matter what.
The for loop iterator was then modified to use the modifiable list in "hold", so its remove() method works, but anywhere else the projectiles field is now unmodifiable for the duration of the iteration.
This is for debug only. Once you identify the problem and correct it, remove the logic again.

Check the documentation of ConcurrentModificationException and ArrayList
https://docs.oracle.com/javase/7/docs/api/java/util/ConcurrentModificationException.html
https://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html
To resolve your issue please check the following code.
For Example,
import java.util.*;
public class HelloWorld{
public static void main(String []args){
List<String> animals = new ArrayList<>();
animals.add("Cat1");
animals.add("Cat2");
animals.add("Cat3");
animals.add("Cat4");
animals.add("Cat5");
for(ListIterator<String> iterator = animals.listIterator(); iterator.hasNext();) {
String name = iterator.next();
if (name.equals("Cat2")) {
iterator.remove();
continue;
}
System.out.println(name);
}
}
}
Cheers!!!

Related

Why does this gives me an error (Multi Thread or ArrayList)?

I have two threads which are running and I need to control if the bullet is touching the enemy but it gives me this problem where I printed "s4". Any idea what happened there? I'm quite a beginner. I'm using Java.
ArrayList<Nemico> nemici= o_orda.getNemici();
for (Nemico nemico : nemici) {
if(Collisioni.ControllaCollisioni(o_navicella, nemico)){
nemici.remove(nemico);
this.o_navicella.vita-=10;
break;
}
for (Proiettile pro : proiettili){
System.out.println("s1");
if(Collisioni.CollsioniProiettile(pro, nemico)){
System.out.println("s2");
nemici.remove(nemico);
System.out.println("s3");
proiettili.remove(pro);
System.out.println("s4");
break;
}
System.out.println("s5");
}
if(ControllaSconfitta()){
this.giocON=false;
Disegna();
}
}
This is the code, I'm sure it will help you.
This code is in a function that checks and update everything every n millisecond.
Thanks for the help
Exception in thread "Thread-7" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at java.lang.Thread.run(Thread.java:745)
and it freeze the game when the collsion happens.
The below code has been updated to use Iterator.remove() instead of ArrayList.remove(). Thank you to #PeterRader for clarifying how these should be used.
If you are intending to modify an ArrayList while iterating over it, you should not use a for-each loop to iterate over it directly. There are two alternative approaches, using an iterator to avoid iterating over the ArrayList itself, or using Java 8's removeIf() function.
I will give a simple (and tested) example of using an iterator, and then attempt to modify your code to do the same thing:
Iterator Example
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
public class IteratorExample{
public static void main(String []args){
ArrayList<Integer> arrList = new ArrayList<Integer>(Arrays.asList(1,2,3));
// Get an Iterator to iterate over the Integers in arrList
Iterator<Integer> iterator = arrList.iterator();
// While iterator hasNext element, access this element with .next() and print it.
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
Modifying your code to use an iterator
Apologies for any spelling mistakes or syntax errors in this version - I have been unable to test it, but given it's only a small piece of code there shouldn't be many and hopefully you will be able to remedy them using the example above. Don't forget to import java.util.Iterator too!
ArrayList<Nemico> nemici= o_orda.getNemici();
Iterator<Nemico> nemiciIterator = nemici.iterator();
while (nemiciIterator.hasNext()) {
nemico = nemiciIterator.next();
if(Collisioni.ControllaCollisioni(o_navicella, nemico)){
nemiciIterator.remove(nemico);
this.o_navicella.vita-=10;
break;
}
Iterator<Proiettile> proIterator = proiettili.iterator();
while (proIterator.hasNext()) {
pro = proIterator.next();
if(Collisioni.CollsioniProiettile(pro, nemico)){
nemiciIterator.remove(nemico);
proIterator.remove(pro);
break;
}
}
if(ControllaSconfitta()){
this.giocON=false;
Disegna();
}
}
...
Resources
Here is a relevant resource. This also includes an example of using removeIf()! https://www.baeldung.com/java-concurrentmodificationexception.

ConcurrentModificationException -> How can I change my code to stop it from throwing this error? [duplicate]

This question already has answers here:
Iterating through a Collection, avoiding ConcurrentModificationException when removing objects in a loop
(31 answers)
Closed 5 years ago.
for (FPlayer p : fPlayer.getFaction().getOnline()) {
p.setFaction(null);
}
Basically, the getOnline method returns an array list of the current FPlayers that are online. When the FPlayer is removed from their faction, the faction is set to null (p.setFaction(null)).
I cannot think about how to change my code to stop it from throwing the ConcurrentModificationException. I have used an iterator but still, it.next().setFaction(null) still throws the same exception.
EDIT:
USING A LIST ITERATOR:
ListIterator<FPlayer> it = fPlayer.getFaction().getOnline().listIterator();
while (it.hasNext()) {
it.next().setFaction(null);
}
Caused by: java.util.ConcurrentModificationException
At the line
it.next().setFaction(null)
EDIT #2:
Set faction method:
public void setFaction(Faction faction) {
if (hasFaction()) {
this.faction.getOnline().remove(this);
}
this.faction = faction;
if (faction != null) {
this.faction.getOnline().add(this);
}
}
This is happening because while iterating you are removing the data from the list .
Couple of solutions .
If the list size is small convert it to array and then loop over
Use for loop for iteration .
for(int i=0;i<fPlayer.getFaction().getOnline().size();i++)
{
// Condition to check if true
if(true)
{
fPlayer.getFaction().getOnline().remove(i);
i--;
}
}
Yes, change your code so it doesn't change the collection inside the loop you are running. For example, create a copy of the collection before iterating.
for (Foo foo : new ArrayList(myFoos)) {
if (foo.isBar()) {
myFoos.remove(foo);
}
}
Iterating and changing the list without the new ArrayList() would have caused a ConcurrentModificationException

NoSuchElementException error iterator anylogic [duplicate]

This question already has an answer here:
java.util.NoSuchElementException using iterator in java
(1 answer)
Closed 7 years ago.
This is my code:
Iterator<H> iter = ((Main) getOwner()).eH.iterator();
while (iter.hasNext()) {
if (iter.next().z.c > p_l) {
if (r) {
if (iter.next().R) {
if (iter.next().p <= 0.7 * s && iter.next().c_l >= p_l) {
if (s_h == null) {
s_h = iter.next();
} else {
if (iter.next().p <= s_h.price) {
s_h = iter.next();
}
}
}
}
}
}
}
but I am getting this error:
Error during model startup:
java.util.NoSuchElementException
java.util.NoSuchElementException
at java.util.ArrayList$Itr.next(ArrayList.java:839)
at d_w.P.I(P.java:681)
at d_w.P.checkIfI(P.java:649)
at d_w.Main.initModelStructure(Main.java:1072)
at d_w.Main.onStartup(Main.java:2775)
at d_w.Main.start(Main.java:2765)
at com.anylogic.engine.Engine.start(Unknown Source)
at com.anylogic.engine.ExperimentSimulation.r(Unknown Source)
at com.anylogic.engine.ExperimentSimulation.run(Unknown Source)
at d_w.Simulation.executeShapeControlAction(Simulation.java:111)
I really not sure why I am getting this error any suggestion is highly appreciated thanks in advance
Calling .next() will retrieve the next element and advances the iterator. You have multiple .next() calls without checking if there is a next element at all.
If you want to keep using the same element that the .next() initially returned, then, replace the first .next() with H next = iter.next(), then access the next variable.
Every time you call next() you don't get the same element, instead you traverse to the next element of the iterator. You should save this value to a variable and use it.

ConcurrentModificationException even though changing values outside of foreach

I have the following code
boolean postojaoJePrijelaz = true;
epsilonStanja = sljedecaStanja;
while(postojaoJePrijelaz) {
for (String epsilonStanje : epsilonStanja) {
for (Prijelaz trenutniPrijelaz : prijelazi) {
postojaoJePrijelaz = false;
if (trenutniPrijelaz.postojiPrijelaz(epsilonStanje.trim(), "$")) {
sljedecaStanja.addAll(trenutniPrijelaz.getSkupIzlaznihStanja());
epsilonSljedecaStanja.addAll(trenutniPrijelaz.getSkupIzlaznihStanja());
postojaoJePrijelaz = true;
}
}
}
epsilonStanja = epsilonSljedecaStanja;
epsilonSljedecaStanja.clear();
}
And the compiler gives e ConcurrentModificationException even though i set epsilonStanje=epsilonSljedecaStanja after I already finished my foreach loop. I tried debuggng, but can't seem to fix this.
The program that I'm making is single-threaded
EDIT:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
at java.util.ArrayList$Itr.next(ArrayList.java:831)
at com.company.Main.main(Main.java:55)
epsilonStanja and epsilonStanja both are pointing to the same object as shown below.
epsilonStanja = sljedecaStanja;
for (String epsilonStanje : epsilonStanja) {
...
sljedecaStanja.addAll(trenutniPrijelaz.getSkupIzlaznihStanja());
...
}
you can't add data while iterating.
Solution: create a separate list and finally merge it as per your requirement or try below code:
epsilonStanja.addAll(sljedecaStanja);
you are assigning the reference of list sljedecaStanja to epsilonStanja. This is the issue.. Try
epsilonStanja = new ArrayList<String>(sljedecaStanja);

Troubles modifying a set with multiple iterators

I'd like to compare elements within a set, in order to merge elements too similar. In order to gain some time, I would like to erase similarities during the iteration.
Here how I try to proceed:
Iterator<Personne> i1 = personnes.iterator();
while (i1.hasNext()) {
Personne personneObservee = i1.next();
Set<Personne> tmp = new HashSet<Personne>();
tmp.addAll(personnes);
Iterator<Personne> i2 = tmp.iterator();
while (i2.hasNext()) {
Personne autrePersonne = i2.next();
if (personneObservee.isSimilarTo(autrePersonne)) {
personnes.remove(autrePersonne);
}
}
result.add(personneObservee.toString());
}
As you can guess from my presence here, it doesn't work, giving me this nice stacktrace :
java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:926)
at java.util.HashMap$KeyIterator.next(HashMap.java:960)
at NameDetectorWithBenefits.mergeSamePersons(NameDetectorWithBenefits.java:41)
at App.main(App.java:71)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:297)
at java.lang.Thread.run(Thread.java:744)
At first, I thought i1 and i2 were iterating over the same set and that I would find an answer here. As a consequence, I create a temporary set each time. However, it didn't resolve the problem.
Any ideas where the trouble might come from ?
While iterating through a set use the iterator to delete elements from the set rather than using set.remove()
// wrong way
personnes.remove(autrePersonne);
//correct way
it.remove();
Use Iterator#remove() rather than Set#remove(Object).
So replace the following line
personnes.remove(autrePersonne);
with
i2.remove();
See here for more details.
You can't update the SET while another thread is iterating it due to which ConcurrentModificationException exception arise.
You are iterating the SET
Iterator<Personne> i1 = personnes.iterator(); and use personnes.remove(autrePersonne); to remove the element.
use Iterator remove method to remove the element
Do it in two steps:
isolate what need removal
remove
.
final Set<Personne> toRemove = new HashSet<>();
for (final Personne personne: personnes) {
for (final Personne autrePersonne: personnes) {
if (person.isSimilarTo(autrePersonne)) {
toRemove.add(autrePersonne);
}
}
}
personnes.removeAll(toRemove);
Also, you need to take care of the case where autrePersonne equals personne

Categories

Resources