将整数值转换为匹配的Java Enum

时间:2023-01-26 14:57:30

I've an enum like this:

我有这样的枚举:

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

Now I get an int from external input and want the matching input - throwing an exception if a value does not exist is ok, but preferably I'd have it be DLT_UNKNOWN in that case.

现在我从外部输入获得一个int并想要匹配的输入 - 如果一个值不存在则抛出异常是好的,但在这种情况下我最好是DLT_UNKNOWN。

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

10 个解决方案

#1


94  

You would need to do this manually, by adding a a static map in the class that maps Integers to enums, such as

您需要手动执行此操作,方法是在将整数映射到枚举的类中添加静态映射,例如

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

#2


30  

There's a static method values() which is documented, but not where you'd expect it: http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html

有一个静态方法values()被记录,但不是你期望的那样: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];}
}

In principle, you can use just values()[i], but there are rumors that values() will create a copy of the array each time it is invoked.

原则上,您可以只使用values()[i],但有传言称values()每次调用时都会创建数组的副本。

#3


14  

You will have to make a new static method where you iterate PcapLinkType.values() and compare:

您必须创建一个新的静态方法,迭代PcapLinkType.values()并比较:

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

That would be fine if it is called rarely. If it is called frequently, then look at the Map optimization suggested by others.

如果它很少被调用那就没问题。如果经常调用它,那么请查看其他人建议的地图优化。

#4


9  

if you have enum like this

如果你有这样的枚举

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

then you can use it like

然后就可以使用它了

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

#5


8  

You can do something like this to automatically register them all into a collection with which to then easily convert the integers to the corresponding enum. (BTW, adding them to the map in the enum constructor is not allowed. It's nice to learn new things even after many years of using Java. :)

您可以执行类似这样的操作,将它们全部自动注册到一个集合中,然后可以轻松地将整数转换为相应的枚举。 (顺便说一句,不允许在枚举构造函数中将它们添加到地图中。即使在使用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);
    }
}

#6


4  

As @MeBigFatGuy says, except you can make your static {...} block use a loop over the values() collection:

正如@MeBigFatGuy所说,除了你可以使你的静态{...}块在values()集合上使用一个循环:

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

#7


4  

I know this question is a few years old, but as Java 8 has, in the meantime, brought us Optional, I thought I'd offer up a solution using it (and Stream and Collectors):

我知道这个问题还有几年的历史,但是就像Java 8一样,同时给我们带来了Optional,我想我会提供一个使用它的解决方案(以及Stream和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 is like null: it represents a case when there is no (valid) value. But it is a more type-safe alternative to null or a default value such as DLT_UNKNOWN because you could forget to check for the null or DLT_UNKNOWN cases. They are both valid PcapLinkType values! In contrast, you cannot assign an Optional<PcapLinkType> value to a variable of type PcapLinkType. Optional makes you check for a valid value first.

可选类似于null:它表示没有(有效)值的情况。但它是null或DLT_UNKNOWN之类的默认值的更类型安全的替代方法,因为您可能忘记检查null或DLT_UNKNOWN情况。它们都是有效的PcapLinkType值!相反,您不能将可选的 值分配给PcapLinkType类型的变量。可选使您首先检查有效值。

Of course, if you want to retain DLT_UNKNOWN for backward compatibility or whatever other reason, you can still use Optional even in that case, using orElse() to specify it as the default value:

当然,如果您想保留DLT_UNKNOWN以实现向后兼容性或其他原因,即使在这种情况下仍然可以使用Optional,使用orElse()将其指定为默认值:

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

#8


3  

You could add a static method in your enum that accepts an int as a parameter and returns a PcapLinkType.

您可以在枚举中添加一个静态方法,该方法接受int作为参数并返回PcapLinkType。

public static PcapLinkType of(int linkType) {

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

        //ETC....

        default: return null;

    }
}

#9


3  

This is what I use:

这是我用的:

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

#10


1  

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


94  

You would need to do this manually, by adding a a static map in the class that maps Integers to enums, such as

您需要手动执行此操作,方法是在将整数映射到枚举的类中添加静态映射,例如

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

#2


30  

There's a static method values() which is documented, but not where you'd expect it: http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html

有一个静态方法values()被记录,但不是你期望的那样: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];}
}

In principle, you can use just values()[i], but there are rumors that values() will create a copy of the array each time it is invoked.

原则上,您可以只使用values()[i],但有传言称values()每次调用时都会创建数组的副本。

#3


14  

You will have to make a new static method where you iterate PcapLinkType.values() and compare:

您必须创建一个新的静态方法,迭代PcapLinkType.values()并比较:

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

That would be fine if it is called rarely. If it is called frequently, then look at the Map optimization suggested by others.

如果它很少被调用那就没问题。如果经常调用它,那么请查看其他人建议的地图优化。

#4


9  

if you have enum like this

如果你有这样的枚举

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

then you can use it like

然后就可以使用它了

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

#5


8  

You can do something like this to automatically register them all into a collection with which to then easily convert the integers to the corresponding enum. (BTW, adding them to the map in the enum constructor is not allowed. It's nice to learn new things even after many years of using Java. :)

您可以执行类似这样的操作,将它们全部自动注册到一个集合中,然后可以轻松地将整数转换为相应的枚举。 (顺便说一句,不允许在枚举构造函数中将它们添加到地图中。即使在使用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);
    }
}

#6


4  

As @MeBigFatGuy says, except you can make your static {...} block use a loop over the values() collection:

正如@MeBigFatGuy所说,除了你可以使你的静态{...}块在values()集合上使用一个循环:

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

#7


4  

I know this question is a few years old, but as Java 8 has, in the meantime, brought us Optional, I thought I'd offer up a solution using it (and Stream and Collectors):

我知道这个问题还有几年的历史,但是就像Java 8一样,同时给我们带来了Optional,我想我会提供一个使用它的解决方案(以及Stream和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 is like null: it represents a case when there is no (valid) value. But it is a more type-safe alternative to null or a default value such as DLT_UNKNOWN because you could forget to check for the null or DLT_UNKNOWN cases. They are both valid PcapLinkType values! In contrast, you cannot assign an Optional<PcapLinkType> value to a variable of type PcapLinkType. Optional makes you check for a valid value first.

可选类似于null:它表示没有(有效)值的情况。但它是null或DLT_UNKNOWN之类的默认值的更类型安全的替代方法,因为您可能忘记检查null或DLT_UNKNOWN情况。它们都是有效的PcapLinkType值!相反,您不能将可选的 值分配给PcapLinkType类型的变量。可选使您首先检查有效值。

Of course, if you want to retain DLT_UNKNOWN for backward compatibility or whatever other reason, you can still use Optional even in that case, using orElse() to specify it as the default value:

当然,如果您想保留DLT_UNKNOWN以实现向后兼容性或其他原因,即使在这种情况下仍然可以使用Optional,使用orElse()将其指定为默认值:

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

#8


3  

You could add a static method in your enum that accepts an int as a parameter and returns a PcapLinkType.

您可以在枚举中添加一个静态方法,该方法接受int作为参数并返回PcapLinkType。

public static PcapLinkType of(int linkType) {

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

        //ETC....

        default: return null;

    }
}

#9


3  

This is what I use:

这是我用的:

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

#10


1  

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