[java] 정수 값을 일치하는 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;
    }
}

이제 외부 입력에서 int를 얻고 일치하는 입력을 원합니다. 값이 존재하지 않으면 예외를 던지는 것이 좋지만, DLT_UNKNOWN 이 경우에있는 것이 좋습니다.

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



답변

Integer를 열거 형에 매핑하는 클래스에 정적 맵을 추가하여 수동으로 수행해야합니다.

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


답변

이 정적 방법이다 되고 문서화,하지만 당신이 그것을 기대하지 여기서 http://docs.oracle.com/javase/tutorial/java/javaOO/enum.htmlvalues()

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

원칙적으로을 사용할 수 values()[i]있지만 values()호출 될 때마다 배열의 복사본을 만드는 소문 이 있습니다.


답변

PcapLinkType.values ​​()를 반복하고 비교하는 새로운 정적 메서드를 만들어야합니다.

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

드물게 호출하면 괜찮을 것입니다. 자주 호출되는 경우 Map다른 사람들이 제안한 최적화 를 살펴보십시오 .


답변

이와 같은 작업을 수행하여 모든 항목을 컬렉션에 자동으로 등록하여 정수를 해당 열거 형으로 쉽게 변환 할 수 있습니다. (BTW, enum 생성자에서 맵에 추가하는 것은 허용되지 않습니다 . 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);
    }
}


답변

이와 같은 열거 형이 있다면

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 */


답변

@MeBigFatGuy가 말했듯이 static {...}블록이 values()컬렉션에 대해 루프를 사용 하도록 만들 수 있다는 점을 제외하고는 다음과 같습니다.

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


답변

나는이 질문이 몇 년 전이라는 것을 알고 있지만, 그 동안 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));
  }
}

Optional 처럼 null : (유효한) 값이없는 경우를 나타냅니다. 그러나 또는 사례 를 확인하는 것을 잊을 수 있기 때문에 더 형식이 안전한 대안 null또는 기본값 입니다. 둘 다 유효한 값입니다! 반대로 유형의 변수 에는 값을 할당 할 수 없습니다 . 먼저 유효한 값을 확인합니다.DLT_UNKNOWNnullDLT_UNKNOWNPcapLinkTypeOptional<PcapLinkType>PcapLinkTypeOptional

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