열거 형의 모든 이름을 String []으로 가져 오기


96

열거 형 요소의 이름을 Strings 배열로 얻는 가장 쉽고 짧은 방법은 무엇입니까?

이것이 의미하는 바는 예를 들어 다음 열거 형이있는 경우입니다.

public enum State {
    NEW,
    RUNNABLE,
    BLOCKED,
    WAITING,
    TIMED_WAITING,
    TERMINATED;

    public static String[] names() {
        // ...
    }
}

names()방법은 배열을 반환합니다 { "NEW", "RUNNABLE", "BLOCKED", "WAITING", "TIMED_WAITING", "TERMINATED" }.


2
나를 넘어서는 것을 정확히 수행하는 네이티브 Enum 메서드가없는 이유와 value () 가져 오기를 단순화하는 get (index)도없는
이유

답변:


91

다음은 모든 enum수업에 대한 한 줄짜리입니다 .

public static String[] getNames(Class<? extends Enum<?>> e) {
    return Arrays.stream(e.getEnumConstants()).map(Enum::name).toArray(String[]::new);
}

Pre Java 8은 덜 우아하지만 여전히 한 줄입니다.

public static String[] getNames(Class<? extends Enum<?>> e) {
    return Arrays.toString(e.getEnumConstants()).replaceAll("^.|.$", "").split(", ");
}

다음과 같이 호출합니다.

String[] names = getNames(State.class); // any other enum class will work

하드 코딩 된 enum 클래스에 대해 간단한 것을 원한다면 :

public static String[] names() {
    return Arrays.toString(State.values()).replaceAll("^.|.$", "").split(", ");
}

2
작업을 수행하는 가장 빠른 방법은 아니지만 좋은 정규식입니다.
ceklock

2
Java 8 솔루션에서 메소드 범위 외부에서 대신 e.getEnumConstants()사용할 수 있습니다YourEnumName.values()
Eido95

1
Eido95 @하여 YourEnumName.values()재사용 할 수없는 클래스에 정적 메소드 호출 모든 열거. 사용 getEnumConstants()을위한 작품 어떤 열거 클래스를. 이 메서드의 아이디어는 답변의 마지막 줄처럼 호출 할 수있는 유틸리티 메서드를 다시 만드는 것입니다.
보헤미안

열거 형에 대한 사용자 정의 레이블이 필요한 경우 열거 형 클래스에서 toString ()을 재정의하십시오.
ralphgabb

설명해 주 Class<? extends Enum<?>> e시겠습니까?
Carmageddon

63

String[]이름에 대한 배열을 만들고 values()모든 열거 형 값을 반환 하는 정적 메서드를 호출 한 다음 값을 반복하고 names 배열을 채 웁니다.

public static String[] names() {
    State[] states = values();
    String[] names = new String[states.length];

    for (int i = 0; i < states.length; i++) {
        names[i] = states[i].name();
    }

    return names;
}

9
values()로컬 변수에 배열을 캐싱하는 대신 매번 새 배열을 생성하여 13 번 호출하는 이유는 무엇 입니까? 대신 재정의 가능한 toString ()을 사용하는 이유는 name()무엇입니까?
JB Nizet

@JBNizet heheh, 나는 실제로 내 IDE에서 이것을 시도했고 상태 배열을 만들기 위해 게으른 방법을 시도했습니다, hehe, 어쨌든 지금 편집했습니다 :)
PermGenError

2
여전히 이름을 반환하지 않지만 toString () 값을 반환합니다.
JB Nizet 2012

@JBNizet 흠, tbh, 나는 name()지금까지 방법 이 있다는 것을 정말로 알고 있습니다 . 나에게 얼마나 어리석은가 : P 알려 주셔서 감사합니다 :)
PermGenError dec

1
나는이 대답을 받아 들였지만 읽기 쉽도록 코드를 개선하는 편집을 제출했습니다.
Konstantin 2012

14

Apache Commons Lang 3을 사용하는 우아한 솔루션은 다음과 같습니다.

EnumUtils.getEnumList(State.class)

목록을 반환하지만 목록을 쉽게 변환 할 수 있습니다. list.toArray()


5
EnumUtils.getEnumList(enumClass)문자열이 아닌 열거 형 값을 반환합니다. 을 사용할 수 EnumUtils.getEnumMap(enumClass).keySet()있지만 순서가 다를 수 있습니다.
Dan Halbert

11

Java 8을 사용할 수 있다면 잘 작동합니다 (Yura의 제안에 대한 대안으로 더 효율적).

public static String[] names() {
    return Stream.of(State.values()).map(State::name).toArray(String[]::new);
}

9

Java 8 사용 :

Arrays.stream(MyEnum.values()).map(Enum::name)
                    .collect(Collectors.toList()).toArray();

2
작동 할 수도 있지만이 구현은 먼저 ArrayList를 만들고 모든 요소를 ​​추가 한 다음 배열을 만들고 모든 것을 다시 복사하는 매우 비효율적입니다.
Daniel Bimschas

조만간 "모든 사람"이 스트림을 사용하여 가장 기본적인 작업을 수행하게 될 것입니다. 이는별로 좋은 생각이 아닙니다.
marcolopes

일반적으로 enum의 요소 수가 적다는 점을 고려하면 Yura의 솔루션이 많은 사용 사례에 적합 할 것이라고 생각합니다. 당연히 상황에 따라 달라집니다 ...
stefan.m

6

나는 이것을 이렇게 쓸 것이다

public static String[] names() {

    java.util.LinkedList<String> list = new LinkedList<String>();
    for (State s : State.values()) {
        list.add(s.name());
    }

    return list.toArray(new String[list.size()]);
}

3

다음과 같이하면됩니다.

public static String[] names() {
  String[] names = new String[values().length];
  int index = 0;

  for (State state : values()) {
    names[index++] = state.name();
  }

  return names;
}

문서 는 대부분의 경우 toString()대신 사용 을 권장name() 하지만 여기에서 이름을 명시 적으로 요청했습니다.


1
특별히 중요하지는 않지만 일반 for 루프는이 상황에서 foreach 루프보다 더 나은 성능을 제공합니다. 또한 values()한 번만 호출하면되는 경우 두 번 호출됩니다.
FThompson

1
@Vulcan 성능은 수십만 번 실행되는 경우에만 문제가 될 것이라고 생각합니다. 게다가 values()컴파일러에 의해 생성 된 메서드이므로 꽤 최적화 된 것 같습니다. 마지막으로, for-each 루프가 표준, 증분 for 루프보다 더 효율적이라는 것을 읽은 것을 기억합니다. 그러나 다시 말하지만 그것은 중요하지 않습니다 .
Konstantin 2012

@Konstantin은 자바의 foreach 루프가 표준 for 루프로 구현된다는 점을 고려하면 foreach 루프가 더 효율적이라는 것을 읽을 때마다 올바르지 않습니다.
sage88 2014

1
@ sage88 각주기에서 증가하는 숫자 인덱스를 사용하여 요소를 검색하는 for 루프를 언급했습니다. 예 : for (int i = 0; i < a.length; i++) /* do stuff */;이 경우 for-each 루프 실제로 더 효율적입니다. 문제에 대한 빠른 SO 검색은 다음과 같습니다. stackoverflow.com/questions/2113216/…
Konstantin

@Konstantin 배열을 반환하는 열거 형 값의 경우와 같이 임의 액세스를 허용하는 데이터 구조가있을 때마다 C 스타일 for 루프가 for 각 루프를 사용하는 것보다 빠릅니다. for each 루프는 반복자를 생성해야하므로 속도가 느려집니다. 게시 한 링크는 get (i)를 사용하여 연결된 목록에서 표준 for 루프를 사용하는 예를 제공합니다. 비 랜덤 액세스 데이터 구조를 사용하는 경우 for each 루프가 더 빠르지 만 배열에서는 오버 헤드가 더 큽니다. 또한 ArrayList가 아닌 기본 배열이기 때문에 .size ()에서 성능 저하가 없습니다.
sage88 2014

3

다른 방법 :

첫 번째

Arrays.asList(FieldType.values())
            .stream()
            .map(f -> f.toString())
            .toArray(String[]::new);

다른 방법

Stream.of(FieldType.values()).map(f -> f.toString()).toArray(String[]::new);

1
에서 경우 toString()작동하지만 때문에 일반적인 경우에 그것은하지 않습니다 toString()오버라이드 (override) 할 수 있습니다. .name()인스턴스 이름 을 String으로 안정적으로 가져 오는 데 사용 합니다 .
보헤미안

2

내 솔루션, 문자열 조작 (가장 빠르지는 않지만 간결함) :

public enum State {
    NEW,
    RUNNABLE,
    BLOCKED,
    WAITING,
    TIMED_WAITING,
    TERMINATED;

    public static String[] names() {
        String valuesStr = Arrays.toString(State.values());
        return valuesStr.substring(1, valuesStr.length()-1).replace(" ", "").split(",");
    }
}

및 java7 호환!
Aquarius Power

1

나는 이런 식으로 그것을 할 것입니다 (그러나 나는 아마도 이름을 배열 대신 수정할 수없는 세트로 만들 것입니다) :

import java.util.Arrays;
enum State {
    NEW,RUNNABLE,BLOCKED,WAITING,TIMED_WAITING,TERMINATED;
    public static final String[] names=new String[values().length];
    static {
        State[] values=values();
        for(int i=0;i<values.length;i++)
            names[i]=values[i].name();
    }
}
public class So13783295 {
    public static void main(String[] args) {
        System.out.println(Arrays.asList(State.names));
    }
}

열거 형 이름을 반복적으로 가져와야하는 경우에도 이와 같은 작업을 수행하지만 names()메서드가 드물게 호출 되기 때문에 그 자리에서 배열을 생성하는 것이 좋습니다.
Konstantin 2012

1

동일한 요구 사항이 있으며 일반 메서드 (ArrayUtils 클래스 내부)를 사용합니다.

public static <T> String[] toStringArray(T[] array) {
    String[] result=new String[array.length];
    for(int i=0; i<array.length; i++){
        result[i]=array[i].toString();
    }
    return result;
}

그리고 enum 안에 STATIC을 정의하십시오.

public static final String[] NAMES = ArrayUtils.toStringArray(values());

Java 열거 형에는 실제로 names () 및 get (index) 메서드가 누락되어 정말 유용합니다.


1

일반적인 방법 (의도 된 말장난) :

String[] myStringArray=new String[EMyEnum.values().length];
for(EMyEnum e:EMyEnum.values())myStringArray[e.ordinal()]=e.toString();

1

@Bohemian의 솔루션에 대해 약간의 테스트를 수행했습니다. 대신 순진한 루프를 사용할 때 성능이 더 좋습니다.

public static <T extends Enum<?>> String[] getEnumNames(Class<T> inEnumClass){
    T [] values = inEnumClass.getEnumConstants();
    int len = values.length;
    String[] names = new String[len];
    for(int i=0;i<values.length;i++){
        names[i] = values[i].name();
    }
    return names;
}

//Bohemian's solution
public static String[] getNames(Class<? extends Enum<?>> e) {
    return Arrays.stream(e.getEnumConstants()).map(Enum::name).toArray(String[]::new);
}

성능에 대한 통계를 제공해야 성능 손실이 중요한지 여부를 사람들이 스스로 판단 할 수 있습니다. 나는 대부분의 사람들이 Enum에 대해 100+ 또는 1000+ 값을 가지지 않을 것이라고 생각합니다.
Rauni Lillemets


0

가장 짧은 것을 원한다면 시도 할 수 있습니다.

public static String[] names() {
    String test = Arrays.toString(values());
    return text.substring(1, text.length()-1).split(", ");
}

가장 짧은 것이 아닙니다 :) 한 줄짜리에 대한 내 대답을 참조하십시오 (여전히 vales()한 번만 호출 됨 )
Bohemian

0

그냥 생각하세요 : 열거 형의 값을 문자열 배열로 반환하는 메서드를 만들 필요가 없을 수도 있습니다.

문자열 배열이 필요한 이유는 무엇입니까? 필요한 경우 값을 사용할 때만 변환하면됩니다.

예 :

for (State value:values()) {
    System.out.println(value); // Just print it.
}

for (State value:values()) {
    String x = value.toString(); // Just iterate and do something with x.
}

// If you just need to print the values:
System.out.println(Arrays.toString(State.values()));

0

Java 7 또는 이전 버전에서 수행하는 또 다른 방법은 Guava를 사용하는 것입니다.

public static String[] names() {
    return FluentIterable.from(values()).transform(Enum::name).toArray(String.class);
}

0

이 시도:

public static String[] vratAtributy() {
    String[] atributy = new String[values().length];
    for(int index = 0; index < atributy.length; index++) {
        atributy[index] = values()[index].toString();
    }
    return atributy;
}

0

열거 형 값을 문자열 목록에 넣고 배열로 변환 할 수 있습니다.

    List<String> stateList = new ArrayList<>();

            for (State state: State.values()) {
                stateList.add(state.toString());
            }

    String[] stateArray = new String[stateList.size()];
    stateArray = stateList.toArray(stateArray);

0

가장 쉬운 방법 :

Category[] category = Category.values();
for (int i = 0; i < cat.length; i++) {
     System.out.println(i  + " - " + category[i]);
}

카테고리가 Enum이름 인 경우

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.