2013-03-12 17 views
16

Chcę uzyskać konkretne wyliczenie na podstawie jego wartości pola.Czy mogę uzyskać wyliczenie na podstawie wartości jego pola?

ENUM:

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


uzyskanie nowego ENUM:

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

Mam stara się wypracować drogę do powyższego przywrócić enum więc może być przekazany przechowywany w HashMap z innymi informacjami o numerze Crime.

Oczekiwany wynik: ASBO

+2

toString() da ci reprezentację łańcuchową Enum, chyba że ją przesłonisz. – Marvo

+0

@Jethro fyi, tak naprawdę nie "inicjujesz nowego wyliczenia" za pomocą tego przykładowego kodu. W rzeczywistości nie można tego zrobić, ponieważ wyliczenia w Javie są efektywnymi singletonami. Naprawdę szukasz aktualnej wartości wyliczeniowej. – sharakan

Odpowiedz

20

Dla porównania, tutaj jest alternatywnym rozwiązaniem z 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; 
    } 
} 
+0

Bardzo dziękuję za to, zamierzam włączyć 'HashMap', jeśli wartość kategorii jest nazywana częściej. Obecnie jest on wywoływany tylko po kliknięciu znacznika mapy, więc wydajność jest obecnie dobra – Jethro

15

Dodaj metodę statyczną do CrimeCategory wyliczenia:

public static CrimeCategory valueOf(String name) { 
    for (CrimeCategory category : values()) { 
     if (category.category.equals(name)) { 
      return category; 
     } 
    }  
    throw new IllegalArgumentException(name); 
} 
+4

Jeśli wydajność jest krytyczna, można użyć statycznej mapy HashMap zawierającej odwzorowania ... – assylias

+1

Rzeczywiście ... Nie byłem pewien, czy rzeczywiste wartości wyliczeniowe są tworzone przed lub po uruchomieniu bloku statycznego init, więc pomyślałem, że I Zachowaj to proste. – sharakan

+0

@sharakan Tak, samo zarejestrowanie się z enum konstruktora do 'mapy', która jest statycznym polem' wyliczenia', będzie NPE. (Rozwiązania: Umieść statystykę w klasie zagnieżdżonej lub przeprowadź pętlę przez 'value()' w statycznym inicjalizatorze umieszczając je na mapie.) –

2

statyczne metody fabryki zwracające stałą wyliczeniową na podstawie wartości pola instancji przyjmują jedną z dwóch form opisanych w innych odpowiedziach: rozwiązanie oparte na i z wartości wyliczeniowych lub rozwiązania opartego na HashMap.

W przypadku wartości wyliczeniowych z małą liczbą stałych, rozwiązanie iteracyjne powinno być tak samo wydajne jak rozwiązanie HashMap (które wymaga obliczenia kodu skrótu, dopasowania go do zasobnika i założenia, że ​​nie będzie kolizji mieszania).

W przypadku większych wyliczeń rozwiązanie oparte na mapie będzie bardziej wydajne (ale wymaga pamięci w pamięci). Jednakże, jeśli metoda fabryczna jest rzadko wywoływana, ogólna poprawa wydajności przy użyciu mapy może wciąż być niezmiernie mała.

Ogólna decyzja o zastosowaniu wyszukiwania iteracyjnego lub wyszukiwania na podstawie mapy dla statycznej metody fabryki ostatecznie zależy od wymagań i środowiska. Nigdy nie jest źle, aby zacząć od iteracyjnego wyszukiwania, a następnie przejść do wdrożenia opartej na mapie, jeśli profilowanie pokazuje rzeczywisty problem z wydajnością.

Wreszcie, od czasu Java 8, API Streams umożliwia oparte na potoku rozwiązanie do mapowania (które powinno mieć wydajność podobną do rozwiązania iteracyjnego). Załóżmy na przykład, że chcesz utworzyć interfejs, którego można użyć na dowolnej klasie wyliczeniowej, aby wyrazić zamiar, że powinien być możliwy do dopasowania przez jedno z jego pól instancji. Nazwijmy ten interfejs Matchable. Ten interfejs definiuje metodę, która zwraca pole instancji, które chcesz dopasować (np. getField()). Interfejs ten może również zdefiniować statyczną metodę fabryczną powrót stały z dowolnego wykonawczego klasy ENUM:

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

Teraz dowolnej klasy enum, które określają, że realizuje Matchable można używać Matchable.forToken() statycznej metody fabryki na znalezienie stałej enum którego wartość pola instancji jest zgodna z podanym parametrem.

Ogólna deklaracja typu E extends Enum<E> & Matchable zapewnia, że ​​token typu przekazywany do metody jako parametr będzie dotyczył klasy enum implementującej Matchable (w przeciwnym razie kod nie zostanie skompilowany).

Powiązane problemy