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

Lyk*_*yke 80 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 final int value;   

    PcapLinkType(int value) {
        this.value= value;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

int val = in.readInt();
PcapLinkType type = ???; /*convert val to a PcapLinkType */
Run Code Online (Sandbox Code Playgroud)

MeB*_*Guy 98

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

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;
}
Run Code Online (Sandbox Code Playgroud)

  • 这似乎是很多不必要的开销.那些真正需要这种类型操作的人可能需要高性能,因为他们是从流/套接字写入/读取,在这种情况下,`values()`的缓存(如果你的枚举值是顺序的)或简单的` switch`语句会轻易地击败这个方法.如果你的`Enum`中只有一些条目,那么添加HashMap的开销就没有多大意义,只是为了方便不必更新`switch`语句.这种方法可能看起来更优雅,但也浪费. (7认同)

184*_*615 30

有一个静态方法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];}
}
Run Code Online (Sandbox Code Playgroud)

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

  • 根据Joshua Bloch _(Effective Java Book)_:**永远不要从序数中获得与枚举相关的值;**您的实现不应该依赖于枚举顺序. (9认同)
  • 实现**的内容是什么?**如果我们实现了一些算法,那么实现不应该依赖于枚举命令_unless_该命令被记录下来.当我们实现enum本身时,可以使用这样的实现细节,就像使用class-private方法一样. (4认同)
  • @ stevo.mit查看了Java 8中的新枚举java.time.Month.Yourth.of(int)静态方法正是Joshua Bloch所说的你应该"永远"做的事情.它根据序数返回月份. (4认同)
  • @stevo.mit 有 _ordered enums_ 和 _unordered enums_。(还有 _bitmask enums_。)将它们仅仅称为“枚举”是不正确的。使用何种表达方式的决定必须基于您所从事的_抽象级别_。使用实现细节(来自较低级别的表达手段)或使用假设(来自较高级别的表达手段)确实是不正确的。至于“_never_”,在人类语言中,从不意味着从不,因为总有一些上下文。(通常,在应用程序编程中,从不……)顺便说一句,http://www.programering.com/a/MzNxQjMwATM.html (2认同)

Boz*_*zho 13

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

public static PcapLinkType forCode(int code) {
    for (PcapLinkType typ? : PcapLinkType.values()) {
        if (type.getValue() == code) {
            return type;
        }
    }
    return null;
 }
Run Code Online (Sandbox Code Playgroud)

如果它很少被调用,那就好了.如果经常调用它,那么请查看Map其他人建议的优化.

  • 这是一个完全荒谬的陈述,没有感觉它的频率.如果它被调用一次,那很好.如果要求每个数据包在10Ge网络上掠过,那么将算法提高200倍是非常重要的.因此,为什么我用"如果被调用了很多"来证明我的陈述. (7认同)
  • 如果经常打电话,可能会很贵.构建静态地图可能会提供更好的摊销成本. (4认同)

Esk*_*ola 9

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


Jac*_*nan 9

如果你有这样的枚举

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后就可以使用它了

PcapLinkType type = PcapLinkType.values()[1]; /*convert val to a PcapLinkType */
Run Code Online (Sandbox Code Playgroud)


Bra*_*ins 5

我知道这个问题已经有几年了,但是由于 Java 8 同时给我们带来了Optional,我想我会提供一个使用它的解决方案(StreamCollectors):

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));
  }
}
Run Code Online (Sandbox Code Playgroud)

Optional就像null:它代表没有(有效)值的情况。但它是一种更类型安全的替代null或默认值,例如DLT_UNKNOWN因为您可能忘记检查nullorDLT_UNKNOWN情况。它们都是有效值PcapLinkType!相反,您不能Optional<PcapLinkType>为类型为 的变量赋值PcapLinkTypeOptional使您首先检查有效值。

当然,如果你想保留是DLT_UNKNOWN为了向后兼容或其他任何原因,Optional即使在这种情况下你仍然可以使用, usingorElse()将其指定为默认值:

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);
  }
}
Run Code Online (Sandbox Code Playgroud)