I'm writing a program as part of tutorial for a beginner Java student. I have the following method and whenever I run it, it gives me the following exception:
java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at Warehouse.receive(Warehouse.java:48)
at MainClass.main(MainClass.java:13)
Here's the method itself, within the class Warehouse:
public void receive(MusicMedia product, int quantity) {
if ( myCatalog.size() != 0) { // Checks if the catalog is empty
// if the catalog is NOT empty, it will run through looking to find
// similar products and add the new product if there are none
for (MusicMedia m : myCatalog) {
if ( !m.getSKU().equals(product.getSKU()) ) {
myCatalog.add(product);
}
}
} else { // if the catalog is empty, just add the product
myCatalog.add(product);
}
}
The problem seems to be with the if else statement. If I don't include the if else, then the program will run, although it won't work properly because the loop won't iterate through an empty ArrayList.
I've tried adding a product just to keep it from being empty in other parts of the code, but it still gives me the same error. Any ideas?
You can't be iterating through the same list you're going to add things to. Keep a separate list of the things you're going to add, then add them all at the end.
You must not modify mCatalog while you're iterating over it. You're adding an element to it in this loop:
for (MusicMedia m : myCatalog) {
if ( !m.getSKU().equals(product.getSKU()) ) {
myCatalog.add(product);
}
}
See ConcurrentModificationException and modCount in AbstractList.
Related
I am working on a game project. So far so good, but i just stuck on ome basic thing and i cant find a solution and make it work properly. I decided to come here and ask you ppl of suggestions.
PROBLEM:
When the player comes to contact with a diamond, i suppose to remove the diamond from the level and from the arraylist containing all the objects in the world. What always happens i get an exception error message after remove() method called.
CODES:
1.Class with the list: EDIT_1
private ArrayList<AbstractObject> objects = new ArrayList<AbstractObject>();
public void removeObject(String name){
ArrayList<AbstractObject> newest = new ArrayList<AbstractObject>();
ListIterator<AbstractObject> delete=objects.listIterator();
while(delete.hasNext()){
if(name.equals(delete.next().getName())){
delete.remove();
}
else{
delete.previous();
newest.add(delete.next());
}
}
objects=newest;
}
2.Player class calling the removeObject method: EDIT_1
public void playerLogic(){
fallingDown();
for(AbstractObject object : this.getWorld().getListOfObjects()){ <--------ERROR HERE
if(this.intersects(object)){
if(object instanceof FinishZone && points>=getWorld().getDiamondCount()){
if(!(getWorld().getManager().isMoreLevels())){
getWorld().getMenu().openMenu(true);
}
else{
this.getWorld().getManager().nextLevel();
}
}
if(object instanceof Diamond){
points++;
this.getWorld().removeObject(object.getName());
}
}
}
}
ERROR:
Exception in thread "Thread-2" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
at java.util.ArrayList$Itr.next(ArrayList.java:831)
at project.objects.characters.Player.playerLogic(Player.java:77)
at project.objects.characters.Player.update(Player.java:70)
at project.world.World.update(World.java:110)
at project.Main.update(Main.java:122)
at project.Main.run(Main.java:65)
at java.lang.Thread.run(Thread.java:745)
I checked up some examples of removing items from arraylist but i havent find the difference.
EDIT_1:
So i figured out how to do it but i always get the error. I edited the removeobject code block. This worked good with a neutral list that i created for testing. I put all the items which i dont want to delete into a new list than ovewritten the old arraylist with the newest one. It worked with no exception error. When i made the same with the game list i want to edit it thrown the same error.
Ill put there the render code too if maybe there is the problem...
public void render(Graphics g) {
if(menu.getChoice()==-1){
menu.render(g);
}
else if(menu.getChoice()==0){
g.setColor(Color.white);
for(AbstractObject tempObj : objects){
tempObj.render(g);
}
}
}
FIXED:
Ill changed the starting list is ListIterator instead of putting items in arrayList before adding it to ListIterator. All methods changed to iterate. Working fine :)
You can't remove object while iterating over a list.
One option - use iterator.remove() - if you iterate with iterator, not the "enhanced for loop". You'll need to slightly modify your loop code, but the functionality will be the same.
Another: Store all objects to remove in an auxiliary list, and remove them all at the end of the loop.
So I've been working on a small tanks program, but whenever I try to run it I get an ArrayIndexOutOf BoundsException on line 477 (http://pastebin.com/k4WNXE6Q).
void placeStations(int Number) {
for (int i = 0; i<Number; i++) {
stations.add(new RefillStation(int(random(0, width)), int(random(0, height))));
// This line of code refuses to work. I get an 'ArrayIndexOutOfBoundsException: -3'
RefillStation station = stations.get(i);
for (Tank tank : tanks) {
if (station.getRectangle().intersects(tank.getRectangle())) {
station.kill();
i=i-1;
}
}
for (Obstacle obstacle : obstacles) {
if (station.getRectangle().intersects(obstacle.getRectangle())) {
station.kill();
i=i-1;
}
}
}
}
I have tried for hours to find an error, but I can see nothing different from the method above, which seems to work fine. I am using the 'i' type for loops in some places because whenever I try to remove something from an index in a modern for loop, it gives me a size change exception. Any Ideas on what I could do to remedy this?
Multiple overlaps with Tanks and Obstacles will cause i to be reduced repeatedly. But you want to kill the station only once: break out of the loop.
for (Tank tank : tanks) {
if (station.getRectangle().intersects(tank.getRectangle())) {
station.kill();
i=i-1;
break;
}
}
for(each) style loops use iterators under the hood and most of the time you can't edit a collection that you're iterating over other than through the remove() method of the iterator object. To do that you'll have to use the iterator explicitly. see this answer
btw variable names with an upper case first character work, but makes it harder for people to read and understand your code.
I am not sure if this is the issue but isn't ArrayList is supposed to have 1st argument for index and second one for the element:
public void add(int index,
E element)
And your code is :
stations.add(new RefillStation(int(random(0, width)), int(random(0, height))));
It is adding element first and then specifying the index.
public void searchOwner(List<Appointments> appts, String owner) {
Appointments theOne = null;
for (Appointments temp : appts) {
if (owner.equalsIgnoreCase(temp.owner.name)) {
System.out.println(temp.data);
temp.setResolved(true);
}
}
}
public void checkRemoval() {
for (Appointments appts : appointments) {
if (appts.resolved == true) {
appointments.remove(appts);
}
//Iterator method used before enhanced for-loop
public void checkRemovalI(){
Iterator<Appointments> it = appointments.iterator();
while(it.hasNext()){
if(it.next().resolved = true){
it.remove();
}
}
}
So far this is where I am encountering my problem. I am trying to check the arrayList of Appointments and see if the field (resolved) is set to true, however I am receiving an ConcurrentModification exception during the searchOwner method when trying to set resolved = to true. I've tried using an Iterator in checkRemoval instead of an enhanced for-loop however that didn't help either. I really only need to get the part where the appointment is set to true to work, the checkRemoval seemed to be working early before implementing the changing of the boolean resolved. Any help will be greatly appreciated, thank you.
I'm willing to bet that the ConcurrentModificationException is not being caused where you say it is, but rather in checkRemoval(), which you're probably calling before the line you mention where you set resolved to true, hence your confusion.
I only say this because:
for (Appointments appts : appointments) {
if (appts.resolved == true) {
appointments.remove(appts);
}
}
is a blatant concurrent modification. You cannot remove elements from a collection while you are iterating through it in a loop. Instead, you need to use an iterator:
public void checkRemoval() {
Iterator<Appointment> apptsIterator = appointments.iterator();
while (apptsIterator.hasNext()){
if (appts.next().resolved == true)
apptsIterator.remove(); //removes the last element you got via next()
}
The ConcurrentModification exception is thrown, using the for loop, where the Collection gets modified. So the issue need not be the code that you haave posted. You might be having a loop over the appts List, which is calling this function.
Posting more of your code might help.
Currently, I'm getting stuck with what it seems to be an unexpected error.
I'm programming with the java language, using eclipse as IDE.
The List in question is declared as follows :
private final List<Integer> resList;
Using the "Watchpoint" feature of eclipse while debugging the program, I've seen the following process :
After returning the resList List two times, and before returning it for the third time, the List became suddenly empty.
If anyone have a suggestion to give me in order to fix that problem, I would be very pleased ?
Concerning the code, I posted all the methods that access the resList list and are invoked in the program :
Here is the first One :
public CloudInformationService(String name) throws Exception {
super(name);
resList = new LinkedList<Integer>();
arList = new LinkedList<Integer>();
gisList = new LinkedList<Integer>();
}
And the second one :
public void processEvent(SimEvent ev) {
int id = -1; // requester id
switch (ev.getTag()) {
...
// A resource is requesting to register.
case CloudSimTags.REGISTER_RESOURCE:
resList.add((Integer) ev.getData());
break;
...
}
}
And finally, The third one :
private static CloudInformationService cis;
public static List<Integer> getCloudResourceList() {
if (cis == null) {
return null;
}
return cis.getList();// The implementation of this method is listed below
}
public List<Integer> getList() {
return resList;
}
Thank you in advance.
Step 1: use ctrl+alt+H to look up references to resList and look for methods calling remove, clear, removeAll. If there are too many methods using resList move on to Step 2.
Step 2: Set breakpoints in the CloudInformationServices constructor, when hit, set up breakpoints in LinkedList/AbstractList (in the JDK) in all remove, clear, removeAll methods. In the breakpoints view, right click on resList and choose instance breakpoints. Pick all your remove, clear, removeAll breakpoints and continue execution. Now you'll get a breakpoint hit and can observe from where the list is being emptied.
Without any more code there isn't much help you can get I'm afraid.
im currently working on a multiple class assignment where i have to add a course based on whether the prerequisites exist within the program.
im storing my courses within the program class using a hashmap. (thought i would come in handy) however, im having a bit of trouble ensuring that these preReqs exist.
here is some code ive currently got going
public boolean checkForCourseFeasiblity(AbstractCourse c) throws ProgramException
{
AbstractCourse[] tempArray = new AbstractCourse[0];
tempArray= courses.keySet().toArray(tempArray);
String[] preReqsArray = new String[1];
preReqsArray = c.getPreReqs();
//gets all course values and stores them in tempArray
for(int i = 0; i < preReqsArray.length; i++)
{
if(courses.containsKey(preReqsArray[i]))
{
continue;
}
else if (!courses.containsKey(preReqsArray[i]))
{
throw new ProgramException("preReqs do not exist"); //?
}
}
return true;
}
ok so basically, tempArray is storing all the keySets inside the courses hashmap and i need to compare all of them with the preReqs (which is an array of Strings). if the preReqs exist within the keyset then add the course, if they dont do not add the course. return true if the course adds otherwise through me an exception. keep in mind my keysets are Strings e.g. a keyset value could be "Programming1" and the required prerquisite for a course could be "programming1". if this is the case add then add the course as the prereq course exists in the keyset.
i believe my error to be when i initialize mypreReqsArray with c.getPreReqs (note: getPreReqs is a getter with a return type String[]).
it would be really great if someone could aid me with my dilemma. ive tried to provide as much as possible, i feel like ive been going around in circles for the past 3 hours :(
-Thank you.
Try something like this, you don't need tempArray. The "for each" loop looks lots nicer too. If you want to throw an Exception I would put that logic in the place that calls this method.
public boolean checkForCourseFeasiblity(AbstractCourse c)
{
for(String each : c.getPreReqs())
{
if(! courses.containsKey(each))
{
return false;
}
}
return true;
}