2012-06-15 15 views
63

Zuvor hatte ich meine Legno Aufzählungen definieren einfach als:Erster Enum mit int-Wert zugeordnet

NO_LEG, LEG_ONE, LEG_TWO 

und durch return LegNo.values()[i]; Aufruf, ich war in der Lage, den Wert mit jedem Enum verbunden zu bekommen.

Aber jetzt habe ich beschlossen, ich will die LegNo Enum NO_LEG die int -1 statt 0 so habe ich beschlossen, einen privaten Konstruktor zu verwenden, zu initialisieren und setzen Sie den Wert int

NO_LEG(-1), LEG_ONE(1), LEG_TWO(2); 

private LegNo(final int leg) { legNo = leg; } 

die einzige Sache ist jetzt, dass, weil ich es so mache die values() Methode wird nicht für die NO_LEG enum funktionieren. Wie bekomme ich die enum mit dem int verbunden? Gibt es eine effiziente Möglichkeit, dies zu tun, außer eine case switch-Anweisung oder ein if-elseif-elseif zu verwenden? Ich kann eine Menge von SO-Fragen sehen, die mit dem Erhalten des int-Wertes aus der enum zu tun sind, aber das bin ich nach der Umkehrung.

Antwort

115

Sie müssen eine Zuordnung innerhalb der Enumeration pflegen.

public enum LegNo { 
    NO_LEG(-1), LEG_ONE(1), LEG_TWO(2); 

    private int legNo; 

    private static Map<Integer, LegNo> map = new HashMap<Integer, LegNo>(); 

    static { 
     for (LegNo legEnum : LegNo.values()) { 
      map.put(legEnum.legNo, legEnum); 
     } 
    } 

    private LegNo(final int leg) { legNo = leg; } 

    public static LegNo valueOf(int legNo) { 
     return map.get(legNo); 
    } 
} 

Der statische Block wird nur einmal aufgerufen, daher gibt es hier praktisch kein Leistungsproblem.

BEARBEITEN: Die Methode wurde in valueOf umbenannt, da sie mehr mit anderen Java-Klassen verknüpft ist.

+0

sorry im nicht sicher, ob ich klar genug war. Ich möchte das Int übergeben und das Enum damit verbinden. –

+0

@ L-Samuels Schätze ich habe deine Frage nicht richtig gelesen. Siehe mein Update. – adarshr

+1

Ich weiß, das scheint offensichtlich, aber benutze es so: 'LegNo foo = LegNo.valueOf (2);'. Der vorherige Code wird eine 'LegNo.LEG_TWO' zurückgeben. – FirstOne

1

Da Ihre Enum nur 3 Elemente enthält, ist der schnellste Weg, eine Reihe von if else zu verwenden, wie Sie vorgeschlagen haben.

edit: Die Antwort, die adarshr bietet, ist besser geeignet für allgemeine Fälle, wo es viele Enum-Werte gibt, aber ich denke, es ist ein Overkill für Ihr Problem.

+0

Eine "Map" in Ihrem Code ist sicherlich kein Overkill. Außerdem macht es die Methode viel sauberer als ein Spaghetti von If-Else-Bedingungen. – adarshr

+0

Ich stimme zu, dass die Map besser ist, wenn Sie viele Enum-Werte haben, aber für 3 Werte würde ich bei einem if/else-Konstrukt bleiben. Es ist eine Frage des Geschmacks, denke ich. – DieterDP

+0

Unabhängig davon, welche Methode wir wählen, sollte die Methodensignatur von 'public LegNo valueOf (int value)' nicht geändert werden. Das If-Else könnte dann in das Enum selbst geschrieben werden. Wenn das If-Else aus der Enum kommt, wird es sicherlich ein nicht so sauberer Code. – adarshr

-4
public enum body 
{ 
    NO_LEG = 0,   // bit 1 
    LEG_ONE = 2,  // bit 2 
    LEG_TWO = 4,  // bit 3 
    NO_ARM = 8,   // bit 4 
    ARM_ONE = 16, // bit 5 
    ARM_TWO = 32 // bit 6 

} 

Verwenden Sie es wie folgt (int) body.LEG_ONE; /// was 2

zurückgibt, das ist auch sehr schnell und leicht lesbar, da es zur Kompilierzeit gemacht wird.

+7

Das ist nicht gültig für Java enums. –

17

Sie können auch eine statische Methode in die Enumeration einschließen, die alle Member durchläuft und die richtige zurückgibt.

public enum LegNo { 
    NO_LEG(-1), 
    LEG_ONE(1), 
    LEG_TWO(2); 

    private int legIndex; 

    private LegNo(int legIndex) { this.legIndex = legIndex; } 

    public static LegNo getLeg(int legIndex) { 
     for (LegNo l : LegNo.values()) { 
      if (l.legIndex == legIndex) return l; 
     } 
     throw new IllegalArgumentException("Leg not found. Amputated?"); 
    } 
} 

Nun, wenn Sie einen ENUM-Wert durch die ganze Zahl erhalten möchten, verwenden Sie einfach:

int myLegIndex = 1; //expected : LEG_ONE 
LegNo myLeg = LegNo.getLeg(myLegIndex); 
+0

Ich nehme an, das wäre eleganter als eine if else if-Anweisung. Aber da es mehr Enumsto zu durchsuchen gibt, wäre die von @adarshr vorgeschlagene Kartenstrategie besser. Obwohl für den Humor stimmen. –

+1

Ich mag die Kartenstrategie auch sehr. Vor allem, wenn das Enum entweder viele Werte hat oder über diesen Mechanismus sehr oft nachgeschlagen werden muss. Wenn das Nachschlagen von Werten mit dem zugehörigen int jedoch relativ selten ist oder Sie viele verschiedene enums mit derselben Lookup-Anforderung haben, würde mein Weg ressourcenschonender sein, da der Overhead für die Map gespeichert wird. Plus, ich finde es für weniger überladenen Code. Ich habe ein paar Anwendungsfälle, in denen ich allerdings definitiv auf den Map-Typ umstellen werde. –

+0

Sie sollten niemals einen zugeordneten Enum-Wert nach seiner Ordinalzahl ableiten. Verwenden einer statischen Karte ist die empfohlene Methode von Java-Architekten. – hfontanez

0
public enum LegNo { 
    NO_LEG(-1), LEG_ONE(1), LEG_TWO(2); 

    private int legNo; 

    private LegNo(int leg) { legNo = leg; } 

    public static LegNo valueOf(int legNo) { 
     for (LegNo leg : LegNo.values()) { 
      if (leg.legNo == legNo) return leg; 
     } 
    } 
} 

assert LegNo.valueOf(2) == LegNo.LEG_TWO 
assert LegNo.valueOf(3) == null 
+4

Akzeptabel für Enums mit <10 Werten, aber für eine große Anzahl von Enum-Werten wegen der Nachschlagekomplexität O (n) völlig unwirksam – Alfishe

10

adarshr's answer auf Java 8 angepasst:

import static java.util.Arrays.stream; 
import static java.util.stream.Collectors.toMap; 

import java.util.Map; 

public enum LegNo { 
    NO_LEG(-1), LEG_ONE(1), LEG_TWO(2); 

    private final int legNo; 

    private final static Map<Integer, LegNo> map = 
      stream(LegNo.values()).collect(toMap(leg -> leg.legNo, leg -> leg)); 

    private LegNo(final int leg) { 
     legNo = leg; 
    } 

    public static LegNo valueOf(int legNo) { 
     return map.get(legNo); 
    } 
} 
4

können Sie Greifen Sie auch auf Enum-Wert zu, der einem gegebenen Integer-Wert entspricht, indem Sie einfach die values ​​() -Methode für enum LegNo aufrufen. Es liefert Feld von LegNo enums:

Nicht gerade das, was er suchte, aber ziemlich nah und obwohl sehr einfach. (Obwohl das Thema tot ist, könnte es für jemand anderen nützlich sein.

) Wert
3

Java 8 Art und Weise mit Standard:

public enum LegNo { 
    NO_LEG(-1), LEG_ONE(1), LEG_TWO(2); 

    private final int legNo; 

    LegNo(int legNo) { 
     this.legNo = legNo; 
    } 

    public static LegNo find(int legNo, Supplier<? extends LegNo> byDef) { 
     return Arrays.asList(LegNo.values()).stream() 
       .filter(e -> e.legNo == legNo).findFirst().orElseGet(byDef); 
    } 
} 

zu nennen:

LegNo res = LegNo.find(0,() -> LegNo.NO_LEG); 

oder mit Ausnahme:

LegNo res = LegNo.find(0,() -> { 
    throw new RuntimeException("No found"); 
});