26

フィールド値に基づいて特定の列挙型を取得したい。

列挙:

public enum CrimeCategory {
    ASBO ("Anti Social Behaviour"),
    BURG ("Burglary"),
    CRIMDAM ("Criminal Damage And Arson"),
    DRUGS ("Drugs"),
    OTHTHEFT ("Other Theft"),
    PUPDISOR ("Public Disorder And Weapons"),
    ROBBERY ("Robbery"),
    SHOPLIF ("Shoplifting"),
    VEHICLE ("Vehicle Crime"),
    VIOLENT ("Violent Crime"),
    OTHER ("Other Crime");

    private  String category;


    private CrimeCategory (String category) {
        this.category = category;
    }

    public String returnString() {
        return category; 
    }
}


新しい列挙型を取得する:

aStringRecivedFromJson = "Anti Social Behaviour"
CrimeCategory crimeCategoryEnum;
crimeCategoryEnum = CrimeCategory.valueOf(aStringRecivedFromJson); 

上記の列挙型を戻す方法を考え出そうとしているので、HashMap他のCrime情報とともに格納して渡すことができます。

期待される結果:ASBO

4

4 に答える 4

37

参考までに、HashMap を使用した代替ソリューションを次に示します。

enum CrimeCategory {
  ASBO("Anti Social Behaviour"),
  BURG("Burglary"),
  CRIMDAM("Criminal Damage And Arson"),
  DRUGS("Drugs"),
  OTHTHEFT("Other Theft"),
  PUPDISOR("Public Disorder And Weapons"),
  ROBBERY("Robbery"),
  SHOPLIF("Shoplifting"),
  VEHICLE("Vehicle Crime"),
  VIOLENT("Violent Crime"),
  OTHER("Other Crime");

  private static final Map<String, CrimeCategory> map = new HashMap<>(values().length, 1);

  static {
    for (CrimeCategory c : values()) map.put(c.category, c);
  }

  private final String category;

  private CrimeCategory(String category) {
    this.category = category;
  }

  public static CrimeCategory of(String name) {
    CrimeCategory result = map.get(name);
    if (result == null) {
      throw new IllegalArgumentException("Invalid category name: " + name);
    }
    return result;
  }
}
于 2013-03-12T20:45:31.950 に答える
26

CrimeCategory列挙型に静的メソッドを追加します。

public static CrimeCategory valueOf(String name) {
    for (CrimeCategory category : values()) {
        if (category.category.equals(name)) {
            return category;
        }
    }    
    throw new IllegalArgumentException(name);
}
于 2013-03-12T19:29:54.647 に答える
4

インスタンス フィールドの値に基づいて列挙定数を返す静的ファクトリ メソッドは、他の回答で説明されている 2 つの形式のいずれかを取ります。列挙値の反復に基づくソリューション、または に基づくソリューションですHashMap

少数の定数を持つ列挙型の場合、反復ソリューションはソリューションと同じくらいパフォーマンスが高くなければなりませんHashMap(これには、ハッシュ コードの計算が必要であり、それをバケットに一致させ、ハッシュの衝突がないことを前提としています)。

より大きな列挙型の場合、マップ ベースのソリューションのパフォーマンスが向上します (ただし、メモリ内のストレージ スペースが必要です)。ただし、ファクトリ メソッドが頻繁に呼び出されない場合、マップを使用することによる全体的なパフォーマンスの向上は、依然として計り知れないほど小さい可能性があります。

反復ルックアップを使用するか、静的ファクトリ メソッドにマップ ベースのルックアップを使用するかの全体的な決定は、最終的には要件と環境によって異なります。プロファイリングで実際のパフォーマンスの問題が示された場合は、反復ルックアップから始めて、マップベースの実装に変更することは決して間違ったことではありません。

最後に、Java 8 以降、StreamsAPI はマッピング用のパイプライン ベースのソリューションを有効にします (反復ソリューションと同様のパフォーマンスを持つ必要があります)。たとえば、任意の enum クラスで使用できるインターフェイスを作成して、そのインスタンス フィールドの 1 つと一致する必要があるという意図を表現するとします。このインターフェイスを と呼びましょうMatchable。このインターフェイスは、一致させたいインスタンス フィールドを返すメソッドを定義します (例: getField())。このインターフェイスは、静的ファクトリ メソッドを定義して、実装する列挙型クラスから定数を返すこともできます。

interface Matchable {

    Object getField();

    public static <E extends Enum<E> & Matchable> E forToken(Class<E> cls, Object token) {

        return Stream.of(cls.getEnumConstants())
            .filter(e -> e.getField().equals(token))
            .findFirst()
            .orElseThrow(() -> new IllegalArgumentException("Unknown token '" +
                    token + "' for enum " + cls.getName()));
    }
}

これで、実装する定義済みの列挙型クラスはMatchable、静的ファクトリ メソッドを使用してMatchable.forToken()、インスタンス フィールド値が指定されたパラメーターと一致する列挙型定数を見つけることができます。

ジェネリック型宣言E extends Enum<E> & Matchableにより、パラメーターとしてメソッドに渡される型トークンが、実装する列挙型クラス用になることが保証されますMatchable(そうでない場合、コードはコンパイルされません)。

于 2016-10-12T18:20:42.147 に答える