2013-03-12 5 views
16

Alan değeri temel alınarak belirli bir numara almak istiyorum.Alanının değerine göre bir numara alabilir miyim?

Enum: Yeni bir Enum Alma

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

Yukarıda için bir yol bulmaya çalışıyorum edilmiş o yüzden bir enum geri getirmek HashMap'da diğer Crime bilgileriyle birlikte iletilebilir.

Beklenen Sonuç: ASBO

+2

toString(), siz onu geçersiz kılmadığınız sürece Enum'un bir String temsilini verecektir. – Marvo

+0

@Jethro fyi, bu örnek kodla gerçekten 'yeni bir numarayı başlat' değilsiniz. Aslında bunu yapamazsınız çünkü Java'daki enumlar etkili bir şekilde bekardır. Gerçekten mevcut bir enum değerine bakıyorsunuz. – sharakan

cevap

20

, burada bir HashMap ile alternatif bir çözümdür örnek alanın değerine bağlı olarak bir enum sabitini döndüren diğer yanıtlarda açıklanan iki formdan birini alır: enum değerlerini ya da HashMap temel alınarak çözüm.

Az sayıda sabiti olan enumlar için, yinelemeli çözüm, HashMap çözümüyle (karma kodun hesaplanmasını, bir kovayla eşleştirilmesini ve karma çarpışmaların olmayacağını varsayarak) performans kadar iyi olmalıdır.

Daha büyük enumlar için, harita tabanlı çözüm daha performanslı olacaktır (ancak bellekte depolama alanı gerektirir). Ancak, fabrika yöntemi nadiren çağrılırsa, bir harita kullanarak genel performans iyileştirmesi hala ölçülemez şekilde küçük olabilir.

Yinelemeli bir arama veya statik fabrika yöntemi için harita tabanlı bir arama kullanma kararı genel olarak gereksinimlerinize ve ortama bağlı olacaktır. Yinelemeli bir arama ile başlamak ve profil oluşturma gerçek bir performans sorunu gösterirse harita tabanlı bir uygulamaya geçmek asla yanlış olmaz. Son olarak, Java 8'den beri, Streams API, haritalama için boru hattı tabanlı bir çözüm sağlar (bu, yinelemeli çözüme benzer bir performansa sahip olmalıdır). Örneğin, herhangi bir enum sınıfında kullanabileceğiniz, örnek alanlarından biriyle eşleşmesi gerektiğini belirten bir arabirim oluşturmak istediğinizi varsayalım. Bu arayüze Matchable diyelim. Bu arabirim, eşleştirmek istediğiniz örnek alanını döndüren bir yöntemi tanımlar (ör. getField()). Ayrıca statik fabrika yöntemini tanımlayabilirsiniz Bu arayüz herhangi uygulayan enum sınıfından sabit dönmek için:

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

Şimdi, herhangi bir enum sınıfı o Matchable kimin enum sabiti bulmak için Matchable.forToken() statik fabrika yöntemi kullanabilirsiniz uygulayan tanımlamak o örnek alan değeri verilen parametreyle eşleşir.

Genel tip bildirimi E extends Enum<E> & Matchable, belirtecin yönteme bir parametre olarak aktarılmasının, Matchable uygulayan bir enum sınıfı için olacağını garanti eder (aksi halde kod derlenmez).

+0

Bunun için çok teşekkür ederim, eğer kategori değeri daha sık denirse, 'HashMap' i ekleyeceğim. Şu anda sadece bir harita işaretçisi tıklandığında çağrılır, bu yüzden performans şu anda tamam – Jethro

15

CrimeCategory enum statik yöntem ekleyin:

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

Veya performans kritikse, eşlemeleri içeren statik bir HashMap kullanılabilir ... – assylias

+1

Gerçekten ... Statik init bloğundan önce veya sonra gerçek enum değerlerinin oluşturulup oluşturulmadığından emin değildim. Basit tut. – sharakan

+0

@sharakan Evet, enum kurucusundan 'Enum' statik alanı olan bir 'Harita'ya kendi kendini kaydettirin NPE. (Çözümler: Statiği iç içe geçmiş bir sınıfa yerleştirin veya döngüden statik bir başlatıcıya yerleştirerek "value()' i döndürün.) –

2

Statik fabrika yöntemleri:

Başvuru için
public static CrimeCategory valueOf(String name) { 
    for (CrimeCategory category : values()) { 
     if (category.category.equals(name)) { 
      return category; 
     } 
    }  
    throw new IllegalArgumentException(name); 
}