enum과 int / String을 편리하게 매핑 써야합니다. 이 경우 두

유한 한 수의 값만 취할 수있는 변수 / 매개 변수로 작업 할 때 다음과 enum같이 항상 Java를 사용하려고합니다 .

public enum BonusType {
  MONTHLY, YEARLY, ONE_OFF
}

내 코드 안에 있으면 잘 작동합니다. 그러나 동일한 목적으로 일반 int(또는 String) 값을 사용하는 다른 코드와 인터페이스해야하는 경우가 많거나 데이터가 숫자 또는 문자열로 저장된 데이터베이스에서 읽거나 써야합니다.

이 경우 두 가지 방법을 모두 변환 할 수 있도록 각 열거 형 값을 정수와 연결하는 편리한 방법을 원합니다 (즉, “가역 열거 형”이 필요합니다).

enum에서 int로 이동하는 것은 쉽습니다.

public enum BonusType {
  public final int id;

  BonusType(int id) {
    this.id = id;
  }
  MONTHLY(1), YEARLY(2), ONE_OFF(3);
}

그런 다음 int 값에 BonusType x = MONTHLY; int id = x.id;.

그러나, 나는 반대로, 즉 int에서 enum으로가는 좋은 방법을 볼 수 없습니다. 이상적으로는

BonusType bt = BonusType.getById(2); 

내가 생각 해낼 수있는 유일한 해결책은 다음과 같습니다.

  • BonusType.values()“int-> enum”맵을 채우는 데 사용하는 조회 메소드를 enum 에 넣은 다음이를 캐시하여 조회에 사용합니다. 작동하지만이 메서드를 사용하는 각 열거 형에 동일하게 복사해야합니다. :-(.
  • 조회 메소드를 정적 유틸리티 클래스에 넣으십시오. 그런 다음 하나의 “조회”메서드 만 필요하지만 임의의 열거 형에 대해 작동하려면 리플렉션을 사용하여 조작해야합니다.

두 가지 방법 모두 이러한 간단한 (?) 문제에 대해 매우 어색해 보입니다.

다른 아이디어 / 통찰이 있습니까?



답변

http://www.javaspecialists.co.za/archive/Issue113.html

솔루션은 열거 형 정의의 일부로 int 값을 사용하여 사용자와 유사하게 시작됩니다. 그런 다음 계속해서 제네릭 기반 조회 유틸리티를 만듭니다.

public class ReverseEnumMap<V extends Enum<V> & EnumConverter> {
    private Map<Byte, V> map = new HashMap<Byte, V>();
    public ReverseEnumMap(Class<V> valueType) {
        for (V v : valueType.getEnumConstants()) {
            map.put(v.convert(), v);
        }
    }

    public V get(byte num) {
        return map.get(num);
    }
}

이 솔루션은 훌륭하며 모든 열거 형 유형이 암시 적으로 Enum 인터페이스를 상속한다는 사실을 기반으로하기 때문에 ‘반사 처리’가 필요하지 않습니다.


답변

열거 형 → 정수

yourEnum.ordinal()

int → 열거 형

EnumType.values()[someInt]

문자열 → 열거 형

EnumType.valueOf(yourString)

열거 형 → 문자열

yourEnum.name()

참고 :
올바르게 지적했듯이 ordinal()버전마다 “불안정”할 수 있습니다. 이것이 내가 항상 데이터베이스에 문자열로 상수를 저장하는 정확한 이유입니다. (실제로 MySql을 사용할 때 MySql 열거 형 으로 저장합니다 !)


답변

나는 이것을 웹에서 발견했고, 구현하기 매우 유용하고 간단했습니다. 이 솔루션은 내가 만든 것이 아닙니다.

http://www.ajaxonomy.com/2007/java/making-the-most-of-java-50-enum-tricks

public enum Status {
 WAITING(0),
 READY(1),
 SKIPPED(-1),
 COMPLETED(5);

 private static final Map<Integer,Status> lookup
      = new HashMap<Integer,Status>();

 static {
      for(Status s : EnumSet.allOf(Status.class))
           lookup.put(s.getCode(), s);
 }

 private int code;

 private Status(int code) {
      this.code = code;
 }

 public int getCode() { return code; }

 public static Status get(int code) {
      return lookup.get(code);
 }

}


답변

이 질문에 대한 답변은 Java 8 릴리스와 함께 구식입니다.

  1. 서수는 데이터베이스와 같은 JVM 외부에서 지속되는 경우 불안정하므로 서수를 사용하지 마십시오.
  2. 키 값으로 정적지도를 만드는 것은 비교적 쉽습니다.

public enum AccessLevel {
  PRIVATE("private", 0),
  PUBLIC("public", 1),
  DEFAULT("default", 2);

  AccessLevel(final String name, final int value) {
    this.name = name;
    this.value = value;
  }

  private final String name;
  private final int value;

  public String getName() {
    return name;
  }

  public int getValue() {
    return value;
  }

  static final Map<String, AccessLevel> names = Arrays.stream(AccessLevel.values())
      .collect(Collectors.toMap(AccessLevel::getName, Function.identity()));
  static final Map<Integer, AccessLevel> values = Arrays.stream(AccessLevel.values())
      .collect(Collectors.toMap(AccessLevel::getValue, Function.identity()));

  public static AccessLevel fromName(final String name) {
    return names.get(name);
  }

  public static AccessLevel fromValue(final int value) {
    return values.get(value);
  }
}


답변

org.apache.commons.lang.enums.ValuedEnum;

많은 상용구 코드를 작성하거나 각 Enum에 대한 코드를 복제하지 않기 위해 ValuedEnum대신 Apache Commons Lang을 사용했습니다.

정의 :

public class NRPEPacketType extends ValuedEnum {
    public static final NRPEPacketType TYPE_QUERY = new NRPEPacketType( "TYPE_QUERY", 1);
    public static final NRPEPacketType TYPE_RESPONSE = new NRPEPacketType( "TYPE_RESPONSE", 2);

    protected NRPEPacketType(String name, int value) {
        super(name, value);
    }
}

용법:

int-> ValuedEnum :

NRPEPacketType packetType =
 (NRPEPacketType) EnumUtils.getEnum(NRPEPacketType.class, 1);


답변

아마도 다음과 같은 것을 사용할 수 있습니다.

interface EnumWithId {
    public int getId();

}


enum Foo implements EnumWithId {

   ...
}

그러면 유틸리티 클래스에서 반영 할 필요가 줄어 듭니다.


답변

이 코드에서는 영구적이고 집중적 인 검색을 위해 사용할 메모리 또는 프로세스가 있고 변환기 배열을 인덱스로 사용하여 메모리를 선택합니다. 도움이 되었기를 바랍니다.

public enum Test{
VALUE_ONE(101, "Im value one"),
VALUE_TWO(215, "Im value two");
private final int number;
private final byte[] desc;

private final static int[] converter = new int[216];
static{
    Test[] st = values();
    for(int i=0;i<st.length;i++){
        cv[st[i].number]=i;
    }
}

Test(int value, byte[] description) {
    this.number = value;
    this.desc = description;
}
public int value() {
    return this.number;
}
public byte[] description(){
    return this.desc;
}

public static String description(int value) {
    return values()[converter[rps]].desc;
}

public static Test fromValue(int value){
return values()[converter[rps]];
}
}