Search code examples
javaconcurrentmodification

Good practice to avoid ConcurrentModification of static collection


Consider class of Player... when player joins the game (object is created), it checks for player with the same name already joined...

public class Player {

    private static List<Player> players = new ArrayList<>();
    private String name;

    public Player(String name) {
        this.name = name;

        for (Player otherPlayer : players) { // Iterating static field
            if (otherPlayer.name.equalsIgnoreCase(name)) {
                otherPlayer.quit("Somebody with the same name joined the game");
            }
        }
    }

    public void quit(String message) {
        players.remove(this); // Modifying static field
        Server.disconnect(this, message);
    }
}

I know that Iterator can deal with this problem, but we don't always know what happens with public static fields in foreign methods and when to use foreach and when to use Iterator instead...

Is there any good practice for this problem?


Solution

  • The first, and more important good practice is called separation of concerns. As in: the Player class should model a single player.

    You are mixing the responsibility of being a Player and managing the overall set of Player objects in one place. Don't do that!

    These two things simply don't belong together. In that sense: there should be a PlayerManager class for example that knows about all players. And also forget about using a static field like this. Because that creates super-tight coupling between the different aspects of your class. What happens for example when you need more than one list of players? What if you have so many players that you want to organize them in buckets, based on certain properties?

    Beyond that, the direct answer is: instead of immediately deleting objects from your list - collect them into a second playersToBeDeleted list. And after iterating the first list, simply use players.removeAll(playersToBeDeleted) for example.

    And talking about good practices: carefully consider if you really want to use Lists - or if Set wouldn't be the better alternative. Lists always imply order, and yuck, they allow to repeatedly add the same object. Whereas a Set gives you "unique elements" semantics for free!