2013-03-12 1 views
16

フィールド値に基づいて特定の列挙型を取得したいと考えています。私は上記がそれて列挙型を取り戻すための方法をうまくしようとしているフィールドの値に基づいて列挙型を取得できますか?

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

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

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


他のCrime情報とともにHashMapに格納されて渡されることができる。

期待される結果:ASBO

+2

toString()は、オーバーライドしない限り、EnumのString表現を提供します。 – Marvo

+0

@Jethro fyi、あなたは実際にそのサンプルコードで新しい列挙型を初期化するわけではありません。実際には、Javaの列挙型は事実上シングルトンであるため、これを行うことはできません。あなたは本当に既存のenum値を探しています。 – sharakan

答えて

20

、ここにHashMapとの代替ソリューションですインスタンスフィールドの値に基づいて列挙型定数を返すものは、他の答えに記述されている2つの形式のうちの1つをとります。列挙型の値をテーティングするか、またはHashMapに基づくソリューションです。

定数の数が少ない列挙型の場合、反復解は、ハッシュコードの計算、バケットとの一致、およびハッシュコリジョンがないと仮定した場合と同じように実行する必要があります。

大規模な列挙型の場合、マップベースのソリューションはパフォーマンスが向上しますが、メモリには記憶領域が必要です。しかし、ファクトリメソッドがあまり頻繁に呼び出されないと、マップを使用することによる全体的なパフォーマンスの改善は、それでもやはり計り知れないほど小さくなる可能性があります。

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

最後に、Java 8以降では、Streams APIはパイプラインベースのマッピングソリューションを可能にします(反復ソリューションと同様のパフォーマンスが必要です)。たとえば、任意の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() staticファクトリメソッドを使用することができます実装して定義した列挙型クラスをインスタンスフィールドの値は、指定されたパラメータと一致します。

generic型宣言E extends Enum<E> & Matchableは、Matchableを実装するenumクラス用であることを保証します(それ以外の場合、コードはコンパイルされません)。

+0

ありがとうございました。カテゴリ値がより頻繁に呼び出される場合は、 'HashMap'を組み込みます。現時点では、マップマーカーがクリックされたときにのみ呼び出されるため、現在のところパフォーマンスは正常です – Jethro

15

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

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

また、パフォーマンスが重要な場合は、マッピングを含む静的HashMapを使用できます。 – assylias

+1

確かに...静的initブロックが実行される前または後に実際の列挙値が作成されているかどうかはわかりませんでした。それを簡単に保つ。 – sharakan

+0

@sharakanはい、enumコンストラクタから 'enum'の静的フィールドである' Map'へのself-registeringはNPEになります。 (ソリューション:入れ子になったクラスや静的な初期化子で 'value()'を使ってループをマップに入れます) –

2

staticファクトリメソッド:参考

public static CrimeCategory valueOf(String name) { 
    for (CrimeCategory category : values()) { 
     if (category.category.equals(name)) { 
      return category; 
     } 
    }  
    throw new IllegalArgumentException(name); 
} 
関連する問題