Frage Konvertieren eines ganzzahligen Werts in übereinstimmende Java Enum


Ich habe ein enum wie folgt:

public enum PcapLinkType {
  DLT_NULL(0)
  DLT_EN10MB(1)
  DLT_EN3MB(2),
  DLT_AX25(3),
  /*snip, 200 more enums, not always consecutive.*/
  DLT_UNKNOWN(-1);
    private final int value;   

    PcapLinkType(int value) {
        this.value= value;
    }
}

Jetzt bekomme ich einen Int von externer Eingabe und möchte die passende Eingabe - eine Ausnahme werfen, wenn ein Wert nicht existiert ist in Ordnung, aber am liebsten hätte ich es DLT_UNKNOWN  In diesem Fall.

int val = in.readInt();
PcapLinkType type = ???; /*convert val to a PcapLinkType */

75
2018-03-13 22:08


Ursprung


Antworten:


Sie müssten dies manuell tun, indem Sie eine statische Map in der Klasse hinzufügen, die Ganzzahlen Enums zuordnet, z

private static final Map<Integer, PcapLinkType> intToTypeMap = new HashMap<Integer, PcapLinkType>();
static {
    for (PcapLinkType type : PcapLinkType.values()) {
        intToTypeMap.put(type.value, type);
    }
}

public static PcapLinkType fromInt(int i) {
    PcapLinkType type = intToTypeMap.get(Integer.valueOf(i));
    if (type == null) 
        return PcapLinkType.DLT_UNKNOWN;
    return type;
}

94
2018-03-13 22:13



Es gibt eine statische Methode values() welche ist dokumentiert, aber nicht dort, wo Sie es erwarten würden: http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html

enum MyEnum {
    FIRST, SECOND, THIRD;
    private static MyEnum[] allValues = values();
    public static MyEnum fromOrdinal(int n) {return allValues[n];}
}

Im Prinzip können Sie nur verwenden values()[i], aber es gibt Gerüchte, dass values() erstellt bei jedem Aufruf eine Kopie des Arrays.


30
2018-02-12 09:14



Sie müssen eine neue statische Methode erstellen, in der Sie PcapLinkType.values ​​() iterieren und vergleichen:

public static PcapLinkType forCode(int code) {
    for (PcapLinkType typе : PcapLinkType.values()) {
        if (type.getValue() == code) {
            return type;
        }
    }
    return null;
 }

Das wäre in Ordnung, wenn es selten genannt wird. Wenn es häufig aufgerufen wird, dann schau dir die an Map von anderen vorgeschlagene Optimierung.


14
2018-03-13 22:12



wenn du so ein enum hast

public enum PcapLinkType {
  DLT_NULL(0)
  DLT_EN10MB(1)
  DLT_EN3MB(2),
  DLT_AX25(3),
  DLT_UNKNOWN(-1);

    private final int value;   

    PcapLinkType(int value) {
        this.value= value;
    }
}

dann kannst du es gerne benutzen

PcapLinkType type = PcapLinkType.values()[1]; /*convert val to a PcapLinkType */

9
2017-12-25 07:06



Sie können so etwas tun, um sie alle automatisch in einer Sammlung zu registrieren, mit der dann ganz einfach die Ganzzahlen in die entsprechende Enumeration konvertiert werden können. (BTW, fügt sie zur Karte im Enum-Konstruktor hinzu ist nicht erlaubt. Es ist schön, auch nach vielen Jahren Java noch etwas Neues zu lernen. :)

public enum PcapLinkType {
    DLT_NULL(0),
    DLT_EN10MB(1),
    DLT_EN3MB(2),
    DLT_AX25(3),
    /*snip, 200 more enums, not always consecutive.*/
    DLT_UNKNOWN(-1);

    private static final Map<Integer, PcapLinkType> typesByValue = new HashMap<Integer, PcapLinkType>();

    static {
        for (PcapLinkType type : PcapLinkType.values()) {
            typesByValue.put(type.value, type);
        }
    }

    private final int value;

    private PcapLinkType(int value) {
        this.value = value;
    }

    public static PcapLinkType forValue(int value) {
        return typesByValue.get(value);
    }
}

8
2018-03-13 22:19



Wie @MeBigFatGuy sagt, außer Sie können Ihre static {...} blockieren Sie eine Schleife über die values() Sammlung:

static {
    for (PcapLinkType type : PcapLinkType.values()) {
        intToTypeMap.put(type.getValue(), type);
    }
}

4
2018-03-13 22:16



Ich weiß, dass diese Frage ein paar Jahre alt ist, aber wie uns Java 8 inzwischen gebracht hat OptionalIch dachte, ich würde eine Lösung anbieten, die es benutzt (und Stream und Collectors):

public enum PcapLinkType {
  DLT_NULL(0),
  DLT_EN3MB(2),
  DLT_AX25(3),
  /*snip, 200 more enums, not always consecutive.*/
  // DLT_UNKNOWN(-1); // <--- NO LONGER NEEDED

  private final int value;
  private PcapLinkType(int value) { this.value = value; }

  private static final Map<Integer, PcapLinkType> map;
  static {
    map = Arrays.stream(values())
        .collect(Collectors.toMap(e -> e.value, e -> e));
  }

  public static Optional<PcapLinkType> fromInt(int value) {
    return Optional.ofNullable(map.get(value));
  }
}

Optional ist wie null: Es stellt einen Fall dar, wenn es keinen (gültigen) Wert gibt. Aber es ist eine mehr typsichere Alternative zu null oder ein Standardwert wie DLT_UNKNOWN weil du vergessen kannst, nach dem zu suchen null oder DLT_UNKNOWN Fälle. Sie sind beide gültig PcapLinkType Werte! Im Gegensatz dazu können Sie keine zuweisen Optional<PcapLinkType> Wert für eine Variable vom Typ PcapLinkType. Optional Sucht zuerst nach einem gültigen Wert.

Natürlich, wenn Sie behalten möchten DLT_UNKNOWN aus Gründen der Abwärtskompatibilität oder aus irgendeinem anderen Grund können Sie trotzdem verwenden Optional auch in diesem Fall, mit orElse() um es als Standardwert anzugeben:

public enum PcapLinkType {
  DLT_NULL(0),
  DLT_EN3MB(2),
  DLT_AX25(3),
  /*snip, 200 more enums, not always consecutive.*/
  DLT_UNKNOWN(-1);

  private final int value;
  private PcapLinkType(int value) { this.value = value; }

  private static final Map<Integer, PcapLinkType> map;
  static {
    map = Arrays.stream(values())
        .collect(Collectors.toMap(e -> e.value, e -> e));
  }

  public static PcapLinkType fromInt(int value) {
    return Optional.ofNullable(map.get(value)).orElse(DLT_UNKNOWN);
  }
}

4
2018-05-16 23:51



Sie könnten in Ihrer Enum eine statische Methode hinzufügen, die ein akzeptiert int als Parameter und gibt a zurück PcapLinkType.

public static PcapLinkType of(int linkType) {

    switch (linkType) {
        case -1: return DLT_UNKNOWN
        case 0: return DLT_NULL;

        //ETC....

        default: return null;

    }
}

3
2018-03-13 22:18



Das ist was ich benutze:

public enum Quality {ENOUGH,BETTER,BEST;
                     private static final int amount = EnumSet.allOf(Quality.class).size();
                     private static Quality[] val = new Quality[amount];
                     static{ for(Quality q:EnumSet.allOf(Quality.class)){ val[q.ordinal()]=q; } }
                     public static Quality fromInt(int i) { return val[i]; }
                     public Quality next() { return fromInt((ordinal()+1)%amount); }
                    }

3
2018-04-10 11:21



static final PcapLinkType[] values  = { DLT_NULL, DLT_EN10MB, DLT_EN3MB, null ...}    

...

public static PcapLinkType  getPcapLinkTypeForInt(int num){    
    try{    
       return values[int];    
    }catch(ArrayIndexOutOfBoundsException e){    
       return DLT_UKNOWN;    
    }    
}    

1
2018-03-13 22:17