Solved ConcurrentModificationException

Discussion in 'Spigot Plugin Development' started by BakedPotato_HD, May 14, 2016.

  1. Why does this throw a CuncurrentModificationException?
    Code (Text):
    for (PlayerShopInfo psi : main.signmanager.playershop){

    }
     
  2. That alone would not. What code is inside the loop?
     
  3. Code (Text):
      Block attached = psi.getChestLocation().getBlock();
                Location chestLoc = attached.getLocation();
                if (loc.equals(chestLoc)) {
                    // TODO CHECK FOR NPE
                    getItemByUniqueID(psi.getItemUniqueID(), loc.getWorld()).remove();
                    main.signManager.playershop.remove(psi);
                }
     
  4. It says the exception is at if (PlayerShopInfo psi : main.signmanager.playershop)
     
  5. ConcurrentModificationExceptions are called when (most) collections are being modified/read from by multiple sources at the same time. If you loop over the shops, and remove an item from it in the loop, there are 2 modifications going on at the same time. You can use an Iterator and Iterator#remove to avoid this
     
    • Agree Agree x 1
  6. You're removing the item while iterating over the collection "main.signManager.playershop.remove(psi);" use an Iterator, or I believe looping over the collection in reverse would solve your issue as well.
     
  7. I've never done anything with an Iterator, how would I do that?
     
  8. @BakedPotato_HD Iterators are actually what Java turns your for-loops into when your code is compiled. Using a for-loop with an Iterator in it is something I like (this format):
    Code (Java):
    for (preLoop; boolean that keeps the loop going; run after each value)
    The Iterator is a class that an Iterable can give you by calling .iterator(). The Iterator class has a hasNext() method to check if it has any more elements, and a next() method to get the next element. If we put that in a simple for-loop:
    Code (Java):
    for (Iterator<PlayerShopInfo> it = main.signmanager.playershop.iterator(); it.hasNext();) {
      PlayerShopInfo info = it.next();
    }
    Notice how I left the last part in the for line empty. Each part of the for loops can be left empty if you don't want to do anything there.
    Now that you have the PlayerShopInfo, you can do yiur stuff with it, and instead of calling main.signmanager.playershop.remove(info), you call it.remove()
     
    • Like Like x 1
    • Agree Agree x 1
  9. Thank you!