将整数值转换为匹配的Java Enum
我有这样的枚举:
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; } }
现在我从外部input获取一个int,并希望匹配的input – 如果一个值不存在,抛出一个exception是好的,但最好是在这种情况下,我想它是DLT_UNKNOWN
。
int val = in.readInt(); PcapLinkType type = ???; /*convert val to a PcapLinkType */
您需要手动执行此操作,方法是在将整数映射到枚举的类中添加一个静态映射,例如
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; }
有一个静态方法values()
被logging,但不是你所期望的: 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];} }
原则上,只能使用values()[i]
,但有传言说values()
会在每次调用时创build一个数组的副本。
你将不得不做一个新的静态方法,你迭代PcapLinkType.values()并比较:
public static PcapLinkType forCode(int code) { for (PcapLinkType typе : PcapLinkType.values()) { if (type.getValue() == code) { return type } } return null; }
这很好,如果它被称为很less。 如果频繁调用,则查看其他人build议的Map
优化。
如果你有这样的枚举
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; } }
那么你可以像使用它
PcapLinkType type = PcapLinkType.values()[1]; /*convert val to a PcapLinkType */
你可以做这样的事情,自动注册到一个集合,然后轻松地将整数转换为相应的枚举。 (顺便说一句,在枚举构造函数中将它们添加到地图中是不允许的,即使经过多年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); } }
正如@MeBigFatGuy所说,除了你可以使你的static {...}
块在values()
集合上使用一个循环:
static { for (PcapLinkType type : PcapLinkType.values()) { intToTypeMap.put(type.getValue(), type); } }
我知道这个问题已经有几年了,但是正如Java 8在此期间带给我们的是Optional
,我想我会提供一个使用它的解决scheme(以及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
就像null
:它代表没有(有效)值的情况。 但是这是一个更types安全的替代方法,可以是null
或默认值,例如DLT_UNKNOWN
因为您可能忘记检查null
或DLT_UNKNOWN
情况。 它们都是有效的PcapLinkType
值! 相反,您不能将Optional<PcapLinkType>
值分配给types为PcapLinkType
的variables。 Optional
使您首先检查一个有效的值。
当然,如果您想保留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); } }
这是我使用的:
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); } }
您可以在您的枚举中添加一个静态方法,该方法接受一个int
作为参数并返回一个PcapLinkType
。
public static PcapLinkType of(int linkType) { switch (linkType) { case -1: return DLT_UNKNOWN case 0: return DLT_NULL; //ETC.... default: return null; } }
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; } }