programing

문자열 값에서 Java 열거형을 검색하려면 어떻게 해야 합니까?

itsource 2022. 7. 3. 23:30
반응형

문자열 값에서 Java 열거형을 검색하려면 어떻게 해야 합니까?

문자열 값(또는 다른 값)에서 열거형을 검색하려고 합니다.다음 코드를 시도했지만 이니셜라이저에서 정적인 코드가 허용되지 않습니다.간단한 방법이 있나요?

public enum Verbosity {

    BRIEF, NORMAL, FULL;

    private static Map<String, Verbosity> stringMap = new HashMap<String, Verbosity>();

    private Verbosity() {
        stringMap.put(this.toString(), this);
    }

    public static Verbosity getVerbosity(String key) {
        return stringMap.get(key);
    }
};

를 사용합니다.valueOf각 Enum에 대해 자동으로 생성되는 메서드입니다.

Verbosity.valueOf("BRIEF") == Verbosity.BRIEF

임의 값의 경우 다음 문자로 시작합니다.

public static Verbosity findByAbbr(String abbr){
    for(Verbosity v : values()){
        if( v.abbr().equals(abbr)){
            return v;
        }
    }
    return null;
}

프로파일러가 지시한 경우에만 나중에 Map 구현으로 넘어갑니다.

모든 값에 대해 반복하고 있는 것은 알지만, 열거값이 3개밖에 없기 때문에 다른 노력을 할 가치가 거의 없습니다.사실 당신이 많은 값을 가지고 있지 않다면 저는 맵을 사용할 필요가 없습니다.

거의 다 왔어.임의의 값에 대해서는, 다음과 같이 시험합니다.

public enum Day { 

    MONDAY("M"), TUESDAY("T"), WEDNESDAY("W"),
    THURSDAY("R"), FRIDAY("F"), SATURDAY("Sa"), SUNDAY("Su"), ;

    private final String abbreviation;

    // Reverse-lookup map for getting a day from an abbreviation
    private static final Map<String, Day> lookup = new HashMap<String, Day>();

    static {
        for (Day d : Day.values()) {
            lookup.put(d.getAbbreviation(), d);
        }
    }

    private Day(String abbreviation) {
        this.abbreviation = abbreviation;
    }

    public String getAbbreviation() {
        return abbreviation;
    }

    public static Day get(String abbreviation) {
        return lookup.get(abbreviation);
    }
}

Java 8 에서는, 다음의 방법으로 실현할 수 있습니다.

public static Verbosity findByAbbr(final String abbr){
    return Arrays.stream(values()).filter(value -> value.abbr().equals(abbr)).findFirst().orElse(null);
}

@라일의 대답은 다소 위험하고, 특히 열거형을 정적인 내부 클래스로 하면 효과가 없는 것을 알았다.대신 enums 앞에 BootstrapSingleton 맵을 로드하는 이와 같은 것을 사용했습니다.

최신 JVM(JVM 1.6 이상)에서는 편집이 더 이상 문제가 되지 않을 것입니다만, JRebel에는 아직 문제가 있다고 생각합니다만, 테스트해 본 적은 없습니다.

먼저 로드:

   public final class BootstrapSingleton {

        // Reverse-lookup map for getting a day from an abbreviation
        public static final Map<String, Day> lookup = new HashMap<String, Day>();
   }

이제 열거형 생성자에 로드합니다.

   public enum Day { 
        MONDAY("M"), TUESDAY("T"), WEDNESDAY("W"),
        THURSDAY("R"), FRIDAY("F"), SATURDAY("Sa"), SUNDAY("Su"), ;

        private final String abbreviation;

        private Day(String abbreviation) {
            this.abbreviation = abbreviation;
            BootstrapSingleton.lookup.put(abbreviation, this);
        }

        public String getAbbreviation() {
            return abbreviation;
        }

        public static Day get(String abbreviation) {
            return lookup.get(abbreviation);
        }
    }

내부 열거형이 있는 경우 열거형 정의 위에 맵을 정의하면 됩니다. 이 맵은 (이론적으로) 사전에 로드해야 합니다.

value Of()는 사용할 수 없습니까?

편집: Btw, 열거형에서 정적 { }을(를) 사용하는 것을 막을 수 없습니다.

다른 사람에게 도움이 될 경우, 여기에 나열되지 않은 옵션에서 Guava의 기능을 사용합니다.

public enum Vebosity {
    BRIEF("BRIEF"),
    NORMAL("NORMAL"),
    FULL("FULL");

    private String value;
    private Verbosity(final String value) {
        this.value = value;
    }

    public String getValue() {
        return this.value;
    }

    private static ImmutableMap<String, Verbosity> reverseLookup = 
            Maps.uniqueIndex(Arrays.asList(Verbosity.values()), Verbosity::getValue);

    public static Verbosity fromString(final String id) {
        return reverseLookup.getOrDefault(id, NORMAL);
    }
}

사용할 수 있는 기본값null,넌 할 수 있다.throw IllegalArgumentException또는 당신의fromString를 반환할 수 있습니다.Optional어떤 행동을 취하든 상관없습니다.

Java 8에서는 스태틱블록 없이1줄로 맵을 초기화할 수 있습니다.

private static Map<String, Verbosity> stringMap = Arrays.stream(values())
                 .collect(Collectors.toMap(Enum::toString, Function.identity()));
public enum EnumRole {

ROLE_ANONYMOUS_USER_ROLE ("anonymous user role"),
ROLE_INTERNAL ("internal role");

private String roleName;

public String getRoleName() {
    return roleName;
}

EnumRole(String roleName) {
    this.roleName = roleName;
}

public static final EnumRole getByValue(String value){
    return Arrays.stream(EnumRole.values()).filter(enumRole -> enumRole.roleName.equals(value)).findFirst().orElse(ROLE_ANONYMOUS_USER_ROLE);
}

public static void main(String[] args) {
    System.out.println(getByValue("internal role").roleName);
}

}

아마도, 이것 좀 보세요.나한텐 효과가 있어.이 작업의 목적은 'RED'와 '/red_color'를 검색하는 것입니다.선언static map및 로딩enum한 번만 접속하면 퍼포먼스상의 이점을 얻을 수고를 덜 수 있습니다.enum는 다수입니다.

public class Mapper {

public enum Maps {

    COLOR_RED("/red_color", "RED");

    private final String code;
    private final String description;
    private static Map<String, String> mMap;

    private Maps(String code, String description) {
        this.code = code;
        this.description = description;
    }

    public String getCode() {
        return name();
    }

    public String getDescription() {
        return description;
    }

    public String getName() {
        return name();
    }

    public static String getColorName(String uri) {
        if (mMap == null) {
            initializeMapping();
        }
        if (mMap.containsKey(uri)) {
            return mMap.get(uri);
        }
        return null;
    }

    private static void initializeMapping() {
        mMap = new HashMap<String, String>();
        for (Maps s : Maps.values()) {
            mMap.put(s.code, s.description);
        }
    }
}
}

의견을 써주세요.

기본값을 사용하고 룩업 맵을 작성하지 않을 경우 이를 처리하는 정적 메서드를 만들 수 있습니다.이 예에서는 예상 이름이 숫자로 시작하는 검색도 처리합니다.

    public static final Verbosity lookup(String name) {
        return lookup(name, null);
    }

    public static final Verbosity lookup(String name, Verbosity dflt) {
        if (StringUtils.isBlank(name)) {
            return dflt;
        }
        if (name.matches("^\\d.*")) {
            name = "_"+name;
        }
        try {
            return Verbosity.valueOf(name);
        } catch (IllegalArgumentException e) {
            return dflt;
        }
    }

세컨더리 값으로 필요한 경우 다른 답변과 마찬가지로 먼저 검색 맵을 클릭합니다.

Enum은 다음 코드로 정의할 수 있습니다.

public enum Verbosity 
{
   BRIEF, NORMAL, FULL, ACTION_NOT_VALID;
   private int value;

   public int getValue()
   {
     return this.value;
   } 

   public static final Verbosity getVerbosityByValue(int value)
   {
     for(Verbosity verbosity : Verbosity.values())
     {
        if(verbosity.getValue() == value)
            return verbosity ;
     }

     return ACTION_NOT_VALID;
   }

   @Override
   public String toString()
   {
      return ((Integer)this.getValue()).toString();
   }
};

자세한 내용은 다음 링크를 참조하십시오.

.Enum::valueOf()Davis & 한 대로 하지만, Gareth Davis & Brad Mace를 해 주십시오.IllegalArgumentException사용된 문자열이 열거에 없는 경우 느려집니다.

언급URL : https://stackoverflow.com/questions/1080904/how-can-i-lookup-a-java-enum-from-its-string-value

반응형