2016-10-01 7 views
-2

Я делаю игру в java с lwjgl и slick. И у меня есть мир, в котором есть аррайалист со всеми предметами, лежащими на земле, которые он должен обновить. Но когда он обновляет элементы во второй раз, он выдает исключение ConcurrentModificationException.Обновление элементов в Arraylist throws ConcurrentModificationException

Как это исправить?

Это полная ошибка: 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)

И это мой код: 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(); 
} 

товара:

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)); 

}

+0

Вставьте свой код здесь в текстовой форме с правильным форматированием. НЕ отправляйте ссылки на внешние источники. – progyammer

ответ

0

Вы удаляете элемент из ArrayList, повторяя его и заставляя его бросать ConcurrentModificationException.

Проследим ваш код;

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

Это требует обновления() на объект Item, который:

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)); 
    } 

Обратите внимание на toBag(). Вы удаляете объект Item из своей коллекции, который вы фактически выполняете итерацией.

В принципе, вы должны использовать итератор вместо прямого удаления из массива.

Для дальнейшего объяснения относятся к подобным вопросам в этом сайте: Iterating through a Collection, avoiding ConcurrentModificationException when removing in loop

+0

у меня есть это: для { \t \t \t товара = iterator.next(); (Iterator итераторных = Game.world.getItems() итератор();; iterator.hasNext().) \t \t \t, если (пункт == это) { \t \t \t \t Iterator.remove(); \t \t \t} \t \t \t \t \t} теперь, но он по-прежнему бросает ошибку – Jakibah

+0

Вы должны использовать его в вашем методе HandleItem, и передать итератор, где вы удалить, так или иначе. – JuniorDev

0

Вы Item.toBag() вызывает это исключение. Строка Game.world.getItems().remove(this); пытается удалить элемент из ArrayList.

Вы не можете изменить список в a для каждого цикла. Вы можете вызвать метод remove только при непосредственном использовании Iterator.