2009-10-15 9 views
19

私は2つの配列を持っています:WallsとNeighbors。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); 

か:私はに設定されたインデックス値をWEST、NORTH、SOUTH、EAST用の静的定数を使用してに戻すべき

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

私のような何かを考えていた

それらを使用するか、Enumの順序付けメソッドを使用しますか?

答えて

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.. 

ところで:列挙型のインスタンスは、慣例により、すべて大文字である必要があり、

enum Dir { 
    NORTH, 
    EAST, 
    SOUTH, 
    WEST 
} 
+2

''壁 'の' EnumSet'です。おそらくそれを同期する必要はありません。 –

13

ほとんどのプログラマーは、このメソッドを使用しないと言います。これは正当な使用の1つのケースです。 あなたのクラスが列挙型と配列の両方をコントロールしていると仮定すると、配列をインデックス化する(常に同期させることができるので)ordinal()メソッドを恐れる理由はありません。

しかし、使用方法が複雑になる場合は、代わりにEnumMapを使用することをお勧めします。

接線問題で
+2

を変更する(おそらく)なしに、あなたのenyumを変更することができます。すなわち、これが示されているコードと有効な場合ですが、ほとんどのコードは簡単にそれのための無効な状況にすることができているいつか変更されます。 – pvgoddijn

1

enumの序を使用します暗黙の順序に依存します。私はあなたの配列に値を意味にリンクするインデックスとして整数値を使用する場合は特に明示的に好きです。私はそのため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; 
    } 
} 

を方向(コンパクトな永続性のために静的ブロック内にマップを作成することによって;静的ブロックなどで一意性検査を行う

3

のJavaDocは

ほとんどのプログラマは この方法のための使用を持っていないだろうと言います。 EnumSetや EnumMapなどの 洗練された列挙型データ 構造で使用するように設計されています。

ほとんどのプログラマは、手動で配列にインデックスを付けてEnumMapまたはEnumSetを使用する方が好きだと言いたいと思います。確かに、列挙型に2つの整数変数を代入する必要があるわけではありません。そうすることで型の安全性が失われるためです。

配列の順序に影響を与えずに列挙定数を並べ替えることができるように柔軟性が必要な場合は、Arneによって説明されているように、インデックスを別の列挙型フィールドに分離できます。

1

控えめな値はJavaコードの順序に基づいているため、これを強くお勧めします。

ordinal()を使用すると、特に永続性のある形式が方程式を入力する場合、非常に保守しにくいコードになります。

たとえば、NORTH_WEST、SOUTH_EASTなどの斜め方向を追加する場合は、 ordinal()を使用している場合は、リストの最後に追加する必要があります。そうしないと、SOUTHだったものがNORTHになることがあります。

あなたは機能

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) 
関連する問題