-2

I am making a game in java with lwjgl and slick. And I have a World that contains a arraylist with all items laying on the ground that it has to update. But when it updates the items a second time it throws a ConcurrentModificationException.

How can I fix this?

This is the full error:Exception in thread "main" java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(Unknown Source) at java.util.ArrayList$Itr.next(Unknown Source) at com.jakibah.infinyvale.World.HandleItems(World.java:43) at com.jakibah.infinyvale.World.Update(World.java:65) at com.jakibah.infinyvale.Game.Update(Game.java:29) at com.jakibah.infinyvale.Canvas.CreateCanvas(Canvas.java:41) at com.jakibah.infinyvale.Game.main(Game.java:16)

And this is my code: World:

package com.jakibah.infinyvale;


public class World {

public Tile[][] map;
private int TilesWide, TileHeight;
public ArrayList<Item> items = new ArrayList<Item>();

public World(int volume) {

    this.TilesWide = volume / 2;
    this.TileHeight = volume / 2;
    map = new Tile[TilesWide][TileHeight];
    for (int i = 0; i < map.length; i++) {
        for (int j = 0; j < map[i].length; j++) {
            map[i][j] = new Tile(TileType.Test, i * 32, j * 32, 32);
        }
    }
}

public World(int[][] newMap) {
    this.TilesWide = newMap[0].length;
    this.TileHeight = newMap.length;
    map = new Tile[TilesWide][TileHeight];
    for (int i = 0; i < map.length; i++) {
        for (int j = 0; j < map[i].length; j++) {
            switch (newMap[j][i]) {
            case 0:
                map[i][j] = new Tile(TileType.Test, i * 32, j * 32, 32);
                break;
            }

        }
    }
}

public synchronized void HandleItems() {
    if (!items.isEmpty()) {
        for (Item i : items) {
            i.Update();
        }
    }
}

public Tile GetTile(int xplace, int yplace) {

    if (xplace < TilesWide && yplace < TileHeight && xplace > -1
            && yplace > -1)
        return map[xplace][yplace];
    else
        return null;
}

public void Update() {
    for (int i = 0; i < map.length; i++) {
        for (int j = 0; j < map[i].length; j++) {
            Tile t = map[i][j];
            t.Update();
        }
    }
    HandleItems();
}

Item:

public class Item {
private ItemType type;
private Texture tex;
private int x, y;
private World w;
private int texturefactor;
private int durability;
private int power;

public Item(ItemType type, Texture tex, int x, int y, World w,int texturefactor, int durability, int power) {
    this.type = type;
    this.tex = tex;
    this.x = y;
    this.y = y;
    this.w = w;
    this.texturefactor = texturefactor;
    this.durability = durability;
    this.power = power;
    this.w.getItems().add(this);
}

public void Draw() {
    Canvas.DrawQuadTex(tex, x, y, texturefactor, texturefactor);
}

public void Update() {
    Draw();
    CheckPickUp();
}
public void CheckPickUp(){
    if(Canvas.isColliding(Game.p.getX(), Game.p.getY(), Game.p.getX() + 32, Game.p.getY() - 32, x, y));
    System.out.println("Colliding");
    this.ToBag();
}

public void ToBag() {
    Inventory i = null;
    i = Game.p.getI();
    Game.world.getItems().remove(this);
    i.getInventory().add(new BagItem(type, i, tex, texturefactor, durability, power));

}

LW001
  • 2,452
  • 6
  • 27
  • 36
Jakibah
  • 53
  • 6

2 Answers2

0

You are removing an item from ArrayList while iterating it and cause it to throw ConcurrentModificationException.

Let's trace your code;

    public synchronized void HandleItems() {
        if (!items.isEmpty()) {
            for (Item i : items) {
                i.Update();
            }
        }
    }

This calls Update() on Item object, which is:

    public void Update() {
        Draw();
        CheckPickUp();
    }
    public void CheckPickUp(){
        if(Canvas.isColliding(Game.p.getX(), Game.p.getY(), Game.p.getX() + 32, Game.p.getY() - 32, x, y));
        System.out.println("Colliding");
        this.ToBag();
    }

    public void ToBag() {
        Inventory i = null;
        i = Game.p.getI();
        Game.world.getItems().remove(this);
        i.getInventory().add(new BagItem(type, i, tex, texturefactor, durability, power));
    }

Pay attention to toBag(). You are removing the Item object from your collection which you are actually in process of iterating.

Basically, you have to use an iterator instead of directly removing from the arraylist.

For further explanation refer to similar questions in this site: Iterating through a Collection, avoiding ConcurrentModificationException when removing in loop

Community
  • 1
  • 1
JuniorDev
  • 1,170
  • 2
  • 9
  • 19
  • I have this: for(Iterator iterator = Game.world.getItems().iterator(); iterator.hasNext();){ Item item = iterator.next(); if(item == this){ iterator.remove(); } } now but It still throws a error – Jakibah Oct 01 '16 at 10:25
  • You have to use it in your HandleItem method, and pass the Iterator where you remove, somehow. – JuniorDev Oct 01 '16 at 10:32
0

You're Item.toBag() is causing this exception. The line Game.world.getItems().remove(this); trying to remove the item from the ArrayList.

You can't modify a List in a for each loop. You can only call remove method when using the Iterator directly.

Ganesh S
  • 510
  • 11
  • 19