Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it bad practice to use an Enum's ordinal value to index an array in Java?

Tags:

java

enums

I have two arrays: Walls and Neighbors.

public boolean[] walls = new boolean[4];
public Cell[] neighbors = new Cell[4];

and I have an Enum:

enum Dir
{
    North,
    South,
    East,
    West
}

Now, I would like to be able to access walls or neighbors by their direction, so I don't have to pass around a bunch of magic indexes.

However, when I was reading the documentation for Enum.ordinal() it said that programmers will have almost no use for this method which made me think it shouldn't be used in this way.

I was thinking of doing something like:

    List<Dir> availableDirections = new ArrayList<Dir>();
    for(Dir direction : Dir.values())
        if (!Neighbors[direction.ordinal()].Visited)
            availableDirections.add(direction);

or even:

return Neighbors[Dir.North.ordinal()];

Should I revert to using static constants for NORTH, SOUTH, EAST, WEST with the index value set to them or use an Enum's ordinal method?

like image 375
Scorcher84 Avatar asked Oct 15 '09 19:10

Scorcher84


4 Answers

On a tangential issue, it might be better to use an EnumMap for your neighbours:

Map<Dir, Cell> neighbours = 
    Collections.synchronizedMap(new EnumMap<Dir, Cell>(Dir.class));

neighbours.put(Dir.North, new Cell());

for (Map.Entry<Dir, Cell> neighbour : neighbours.entrySet()) {
    if (neighbour.isVisited()) { ... }
}

etc..

BTW: Enum instances should by convention be all caps,

enum Dir {
    NORTH,
    EAST, 
    SOUTH,
    WEST
}
like image 61
toolkit Avatar answered Nov 05 '22 02:11

toolkit


The documentation only says that most programmers will have no use for the method. This is one case of legitimate use. Assuming your class controls both the enum and the array, there is no reason to fear the ordinal() method for indexing the array (since you can always keep them in sync).

However, if your usage gets any more complicated, you will likely want to use an EnumMap instead, as has been suggested.

like image 36
Michael Myers Avatar answered Nov 05 '22 04:11

Michael Myers


You can also enhance an enum (index clockwise):

enum Dir
{
  NORTH(0),
  SOUTH(2),
  EAST(1),
  WEST(3);

  private final int index;

  private Dir(int index) {
    this.index = index;
  }

  public int getIndex() {
    return index;
  }

}
like image 13
Arne Burmeister Avatar answered Nov 05 '22 02:11

Arne Burmeister


The JavaDoc says

Most programmers will have no use for this method. It is designed for use by sophisticated enum-based data structures, such as EnumSet and EnumMap.

I think they want to say that most programmers will prefer using an EnumMap or EnumSet over manually indexing into an array. They certainly don't mean that you should substitute a couple of integer variables for your enum, as you would lose type safety in doing so.

If you need the flexibility to be able to reorder the enum constants without affecting the order in the array you can isolate the index into another field of the enum as has been described by Arne.

like image 4
meriton Avatar answered Nov 05 '22 03:11

meriton