enum内のすべての名前をString []として取得する


95

enum要素の名前を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メソッドがない...そして、get(index)がvalue()の取得を単純化する
marcolopes

回答:


91

以下は、任意のenumクラスのワンライナーです。

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

以前のJava 8は、エレガントではありませんが、依然として1行です。

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

ハードコードされた列挙型クラスに対して単純なものが必要な場合:

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

2
仕事をするための最速の方法ではなく、素晴らしい正規表現。
ceklock

2
Java 8ソリューションでは、メソッドスコープの外で、代わりにe.getEnumConstants()使用できますYourEnumName.values()
Eido95 '27

1
@ Eido95を使用するYourEnumName.values()と、クラスで静的メソッドが呼び出されますこれは、列挙型で再利用できません。enumクラスのgetEnumConstants()作品を使用します。このメソッドのアイデアは、回答の最後の行のように呼び出すことができるユーティリティメソッドを再作成することです。
ボヘミアン

enumのカスタムラベルが必要な場合は、enumクラスのtoString()をオーバーライドします。
ラルフガブ2018年

説明していただけますClass<? extends Enum<?>> eか?
カルマゲドン

63

String[]名前の配列を作成し、values()すべての列挙値を返す静的メソッドを呼び出してから、値を反復処理して名前の配列を設定します。

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へへ、私は実際にこれを自分のIDEで試してみて、状態配列を作成するのに怠惰な方法だと思いますね、へへ、とにかく今それを編集しました:)
PermGenError

2
あなたはまだ名前を返していませんが、toString()の値を返しています。
JB Nizet

@JBNizetうーん、tbh、私はname()今まで方法があったことを本当に知っています。なんてばかげている:P私に知らせてくれてありがとう:)
PermGenError

1
私はこの回答を受け入れましたが、コードを改善して読みやすくする編集を送信しました。
コンスタンティン

14

Apache Commons Lang 3を使用したエレガントなソリューションは次のとおりです。

EnumUtils.getEnumList(State.class)

リストを返しますが、リストを簡単に変換できます list.toArray()


5
EnumUtils.getEnumList(enumClass)文字列ではなく列挙値を返します。を使用できますEnumUtils.getEnumMap(enumClass).keySet()が、順序が異なる場合があります。
Dan Halbert、2016年

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 2015

列挙型の要素の数は通常かなり少ないという事実を考慮すると、Yuraの解決策は多くのユースケースで問題ないと思います。当然、それは特定の状況に依存します...
stefan.m 2017年

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()1回だけ呼び出す必要がある場合は、2回呼び出されます。
FThompson

1
@Vulcanパフォーマンスが問題になるのは、何十万回も実行された場合のみだと思います。さらに、values()コンパイラによって生成されたメソッドなので、かなり最適化されていると思います。最後に、for-eachループは標準のインクリメンタルなforループよりも効率的であるとどこかで読んだことを覚えていますが、それでも重要ではありません
コンスタンティン

@Konstantinは、Javaのforeachループが標準のforループで実装されていることを考慮すると、foreachループがより効率的であると読んだ場合は誤りです。
sage88 14年

1
@ sage88私は、各ループで増分する数値インデックスを使用して要素を取得するforループについて言及していました。例:for (int i = 0; i < a.length; i++) /* do stuff */;この場合、for-eachループ実際にはより効率的です。問題の迅速なSO検索は私達にこれを与える:stackoverflow.com/questions/2113216/...
コンスタンチン

@Konstantin配列を返す列挙値の場合のように、ランダムアクセスを許可するデータ構造がある場合はいつでも、Cスタイルのforループはfor eachループを使用するよりも高速です。for eachループは反復子を生成する必要があるため、処理が遅くなります。あなたが投稿したリンクは、get(i)を使用してリンクされたリストで標準のforループを使用する例を示していますが、これはもちろん悪くなります。非ランダムアクセスデータ構造を使用すると、for eachループはより高速になりますが、配列ではオーバーヘッドが大きくなります。また、これはArrayListではなくプリミティブ配列であるため、.size()によるパフォーマンスへの影響はありません。
sage88 2014年

3

別の方法:

最初の1つ

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()上書きすることができます。.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()メソッドが呼び出されるのは控えめなので、その場で配列を生成することは問題ないと思います。
コンスタンティン

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

そして、列挙型の内部で静的を定義します...

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 2018


0

あなたが最短にしたい場合は、試すことができます

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

最短ではありません:)ワンライナーについての私の答えを参照してください(まだ一vales()度しか起動しません)
ボヘミアン

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.