numeric - Convierta un valor entero para coincidir con Java Enum




numbers set (9)

Esto es lo que uso:

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

Tengo una enumeración como esta:

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

Ahora obtengo un int de entrada externa y quiero la entrada correspondiente - lanzar una excepción si un valor no existe está bien, pero preferiblemente sería DLT_UNKNOWN en ese caso.

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

Como dice @MeBigFatGuy, excepto que puedes hacer que tu bloque static {...} use un ciclo sobre la colección values() :

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

Sé que esta pregunta tiene algunos años, pero como Java 8, mientras tanto, nos trajo Optional , pensé que ofrecería una solución para usarlo (y Stream y 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 es como null : representa un caso cuando no hay un valor (válido). Pero es una alternativa más segura a los valores null o predeterminados, como DLT_UNKNOWN ya que puede olvidarse de verificar los casos null o DLT_UNKNOWN . ¡Ambos son valores válidos de PcapLinkType ! Por el contrario, no puede asignar un valor Optional<PcapLinkType> a una variable de tipo PcapLinkType . Optional hace verificar primero un valor válido.

Por supuesto, si desea retener DLT_UNKNOWN por compatibilidad con versiones anteriores o por cualquier otro motivo, aún puede usar Optional incluso en ese caso, usando orElse() para especificarlo como el valor predeterminado:

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

si tienes enum como este

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

entonces puedes usarlo como

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

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

Tendría que hacer esto manualmente, agregando un mapa estático en la clase que asigna enteros a las enumeraciones, como

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

Puede hacer algo como esto para registrarlos automáticamente en una colección para luego convertir fácilmente los enteros en la enumeración correspondiente. (Por cierto, agregarlos al mapa en el constructor enum no está permitido . Es bueno aprender cosas nuevas incluso después de muchos años usando Java. :)

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

Puede agregar un método estático en su enumeración que acepte un int como parámetro y devuelva un PcapLinkType .

public static PcapLinkType of(int linkType) {

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

        //ETC....

        default: return null;

    }
}

Esa es toda la idea de un bloque finalmente. Le permite asegurarse de que realiza limpiezas que, de lo contrario, podrían omitirse porque, por supuesto, entre otras cosas, regresa.

Finalmente, recibe una llamada independientemente de lo que suceda en el bloque de prueba (a menos que llame a System.exit(int) o la Máquina Virtual de Java salga por alguna otra razón).





java