2009-10-15 26 views
19

我有兩個數組:牆和鄰居。在Java中使用Enum的序數值來索引數組是不好的做法嗎?

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

,我有一個枚舉:

enum Dir 
{ 
    North, 
    South, 
    East, 
    West 
} 

現在,我希望能夠通過自己的方向來訪問牆壁或鄰居,所以我不必繞過一堆魔索引。

但是,當我閱讀Enum.ordinal()的文檔時,它說程序員幾乎不會使用這種方法,這使得我認爲它不應該以這種方式使用。

我的想法做類似的:

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

甚至:

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

我應該恢復使用靜態常量的北,南,東,西與設置爲索引值他們還是使用枚舉的序數方法?

回答

16

在切線問題,它可能是最好使用EnumMap的爲你的鄰居:

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 Dir { 
    NORTH, 
    EAST, 
    SOUTH, 
    WEST 
} 
+2

'EnumSet'用於'walls'。可能不需要它被同步。 – 2009-10-15 19:47:55

13

該文檔只說大多數程序員將無法使用該方法。這是合法使用的一種情況。 假設你的類控制枚舉和數組,沒有理由擔心ordinal()索引數組的方法(因爲你可以始終保持它們同步)。

但是,如果您的使用情況變得更加複雜,您可能會想要使用EnumMap代替,正如所建議的。

+2

雖然這是用代碼顯示一個有效的情況下,大部分的代碼被某個時候改變它可以很容易地使之成爲它一個無效的情況。 – pvgoddijn 2009-10-15 23:02:46

1

使用枚舉的序供您使用取決於隱式順序。我喜歡明確地表達,尤其是如果你使用整數值作爲你的數組鏈接值到意義的索引。

在這種情況下,因此我會選擇使用final static int NORTH = 0

13

您還可以增強一個枚舉(指數順時針):如果你不堅持的陣列或以任何其它

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

} 
2

方式使你自己依賴於你的enum類的不同版本,使用ordinal()是安全的。

如果你想不想依靠枚舉值的隱式排序,你可以引入私人指數值:

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

    private int _index; 

    private Direction (int index_) 
    { 
    _index = index_; 
    } 

    public int getIndex() 
    { 
    return _index; 
    } 
} 

從這裏可以很容易地都允許對指數的容易查找到方向(通過在靜態塊中創建一個用於緊湊持久性的Map;在靜態塊等中進行唯一性檢查

3

的JavaDoc的說

大多數程序員不會使用了 此方法。它被設計用於 複雜的基於枚舉的數據 結構,例如EnumSet和 EnumMap。

我想他們想說,大多數程序員會更喜歡使用EnumMap或EnumSet來手動索引到數組中。他們當然不意味着你應該用你的枚舉來替換幾個整型變量,因爲這樣做會失去類型安全性。

如果您需要靈活性來重新排列枚舉常量而不影響數組中的順序,您可以將索引隔離到另一個枚舉字段,如Arne所述。

1

我強烈建議不要這樣做,因爲Ordinal值是基於您的java代碼中的順序。

使用ordinal()將使您的代碼非常難以維護,特別是如果某種形式的持久性進入等式。

例如,如果您決定添加對角線方向,如NORTH_WEST,SOUTH_EAST。 如果使用ordinal(),則必須將這些添加到列表的底部,否則以前是SOUTH的可能會變成NORTH。

即您可以將您的enyum更改爲無(可能)改變功能

N (is now 0 was 0) 
NE (is now 1) 
E (is now 2 was 1) 
SE (is now 3) 
S (is mow 4 was 2) 
SW (is now 5) 
W (is now 6 was 3) 
相關問題