1

他の2つの列挙型に基づいて列挙値を取得するための美的な方法はありますか?私がやりたいのは、次の例のように2つの列挙型引数の状態を取得することです。

public enum State{

ONE_STATE,
SECOND_STATE;
THIRD_STATE;

public static State getState(Direction dir, Type type) {
    if (dir.equals(Direction.LEFT) && type.equals(Type.BIG)) {
        return ONE_STATE;
    }
    else if (dir.equals(Direction.RIGHT) && type.equals(Type.SMALL)) {
        return SECOND_STATE;
    }
    else if (dir.equals(Direction.UP) && type.equals(Type.SMALL)) {
        return FIRST_STATE;
    }
    return THIRD_STATE;
}

}

もちろんこれは言葉になりますが、そのような可能性の数は時間とともに増えるので、私の意図は何かをより明確にすることです。

4

6 に答える 6

0

ネストされたEnummMapを使用します。「EffectiveJava」の本(項目33)は、これが最良の解決策である理由を説明しています。

// Using a nested EnumMap to associate data with enum pairs
public enum Phase {
    SOLID, LIQUID, GAS;
    public enum Transition {
        MELT(SOLID, LIQUID), FREEZE(LIQUID, SOLID),
        BOIL(LIQUID, GAS), CONDENSE(GAS, LIQUID),
        SUBLIME(SOLID, GAS), DEPOSIT(GAS, SOLID);
        final Phase src;
        final Phase dst;
        Transition(Phase src, Phase dst) {
            this.src = src;
            this.dst = dst;
        }
        // Initialize the phase transition map
        private static final Map<Phase, Map<Phase,Transition>> m =
                new EnumMap<Phase, Map<Phase,Transition>>(Phase.class);
        static {
            for (Phase p : Phase.values())
                m.put(p,new EnumMap<Phase,Transition>(Phase.class));
            for (Transition trans : Transition.values())
                m.get(trans.src).put(trans.dst, trans);
        }
        public static Transition from(Phase src, Phase dst) {
            return m.get(src).get(dst);
        }
    }
}
于 2013-02-21T15:26:34.113 に答える
0

列挙型にはフィールドを含めることができます。次のように試すことができます。

public enum State {
    ONE_STATE(Direction.LEFT, Type.BIG),
    ...

    Direction d;
    Type t;

    private State(Direction d, Type t) {
        ...
    }

    public static State getState(Direction d, Type t) {
        for (State s : State.values()) {
            if (s.d == d && s.t == t) {
                return s;
            }
        }
        return null;
    }
}
于 2013-02-21T15:20:48.447 に答える
0

次のように、DirectionとTypeを列挙型のメンバーとして配置するのはどうですか。

public enum State {

    ONE_STATE(Direction.LEFT, Type.BIG),
    SECOND_STATE(Direction.RIGHT, Type.SMALL);
    THIRD_STATE(Direction.UP, Type.SMALL);

    private Direction direction;
    private Type type;

    private State(Direction direction, Type type) {
        this.direction = direction;
        this.type = type;
    }

    public static State getState(Direction dir, Type type) {
        for (State state : values()) {
            if (state.direction == dir && state.type == type) {
                return state;
            }
        }
        return THIRD_STATE;
    }
}

列挙型ごとに複数の異なる組み合わせがある場合、これは機能しないことに注意してください。その場合、別の投稿者が提案するようなルックアップテーブルを使用する必要があります。たとえば、を使用できますMap<Pair<Direction, Type>, State>。(Javaにはクラスがありませんが、Pair<T, U>クラスを簡単に作成したり、さまざまなライブラリで見つけることができます。)

于 2013-02-21T15:20:56.347 に答える
0

カプセル化して、具体的なクラスに入れることができますDIRECTIONTYPEたとえばEnumGroup)。そして、 enumHashmapのオブジェクトEnumGroupおよび値として key を含む を作成します。このようにして、とvalue の複数の組み合わせの値を保存できます。同じ値を持つ 2 つの異なる値を持つこともできます。これがコードデモです。valueStatestateDIRECTIONSTATEEnumGroupstate

import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
class EnumGroup 
{
    Direction direction;
    Type type;
    private EnumGroup(){}//To prevent parmeterless construction
    public EnumGroup(Direction direction , Type type)
    {
        if (direction==null || type == null)
        {
            throw new IllegalStateException("null is not allowed");
        }
        this.direction = direction;
        this.type = type;
    }
    @Override
    public int hashCode()
    {
        return direction.toString().hashCode() + type.toString().hashCode() ;
    }
    @Override
    public boolean equals(final Object other)
    {
        if (other == null || !(other instanceof EnumGroup))
        {
            return false;
        }
        if (this == other)
        {
            return true;
        }
        EnumGroup temp = (EnumGroup)other;
        if (temp.type == this.type && temp.direction == this.direction)
        {
            return true;
        }
        return false;
    }
}
enum Direction
{
    LEFT,RIGHT,DOWN,UP,ACCROSS;
}
enum Type
{
    BIG,SMALL,MEDIUM;
}
enum State
{
    ONE_STATE,FIRST_STATE,SECOND_STATE,THIRD_STATE;
    private static final Map<EnumGroup,State> map = new HashMap<EnumGroup,State>();
    static
    {
        map.put(new EnumGroup(Direction.LEFT,Type.BIG),ONE_STATE);
        map.put(new EnumGroup(Direction.RIGHT,Type.SMALL),SECOND_STATE);
        map.put(new EnumGroup(Direction.UP,Type.SMALL),FIRST_STATE);
        /*
        .
        .
        .
        */
    }
    public static State getState(EnumGroup eGroup) 
    {
        State state = map.get(eGroup);
        return state == null ? THIRD_STATE : state;
    }
}
public class EnumValueByArgument
{
    public static void main(String st[])
    {
        ArrayList<EnumGroup> list = new ArrayList<EnumGroup>();
        for (Direction direction : Direction.values())
        {
            for (Type type : Type.values() )
            {
                list.add(new EnumGroup(direction,type));
            }
        }
        for (EnumGroup eGroup : list )
        {
            System.out.println(State.getState(eGroup));
        }
    }
}
于 2013-02-21T18:18:28.660 に答える
0

switchs の代わりに es を使用できますがif、コードは短くなりません。より明確であるという利点があり、また、IDE によっては、switchケースが欠落している場合にエラーを発生させることができます。

ほとんどのアイテムを持つ列挙型をアウターswitchにし、その他をインナーにしswitchます。

にフィールドを追加することは、 とState enumの組み合わせが 1 つしかない場合にのみ機能します。DirectionTypeState

switch(dir) {
  case LEFT:
  {
    switch(type) {
      case BIG:
      ...
于 2013-02-21T15:25:15.953 に答える
0

ルックアップ テーブルを使用しないのはなぜですか。行の配列 - 各行には 2 つの入力と 1 つの出力が含まれます。

LEFT,  BIG,   ONE_STATE
RIGHT, SMALL, SECOND_STATE

などを参照し、検索に失敗した場合に検索してデフォルトを返すメソッドを提供します。

それができない場合は、二重ディスパッチを調査できます

于 2013-02-21T15:19:20.267 に答える