एक स्ट्रिंग में सभी नाम एक स्ट्रिंग के रूप में प्राप्त करना []


95

एस के एक सरणी के रूप में एनम तत्वों के नाम पाने के लिए सबसे आसान और / या सबसे छोटा तरीका Stringक्या है?

इससे मेरा तात्पर्य यह है कि, उदाहरण के लिए, मेरे पास निम्नलिखित एनम थी:

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

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

names()विधि सरणी वापसी होगी { "NEW", "RUNNABLE", "BLOCKED", "WAITING", "TIMED_WAITING", "TERMINATED" }


2
एक देशी एनम पद्धति क्यों नहीं है जो वास्तव में ऐसा करती है कि यह मेरे से परे है ... और मूल्य प्राप्त करने को सरल बनाने के लिए एक (सूचकांक) भी प्राप्त करें ()
मार्कोलोप्स

जवाबों:


91

यहाँ किसी भी enumवर्ग के लिए वन-लाइनर है :

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

प्री-जावा 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

यदि आप एक कठिन-कोडित एनम वर्ग के लिए कुछ सरल चाहते हैं:

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

2
काम करने का सबसे तेज़ तरीका नहीं, लेकिन अच्छा रेगेक्स।
3

2
जावा 8 समाधान में, एक विधि दायरे के बाहर, e.getEnumConstants()आप के बजाय उपयोग कर सकते हैंYourEnumName.values()
Eido95

1
@ Eido95 का उपयोग करके YourEnumName.values()क्लास पर एक स्टैटिक तरीका बताया जा रहा है, जिसका किसी भी एनम के लिए पुन: उपयोग नहीं किया जा सकता है । किसी भी एनम वर्ग के getEnumConstants()लिए कार्यों का उपयोग करना । इस विधि के साथ विचार एक उपयोगिता विधि को फिर से बनाने के लिए है जिसे आप उत्तर की अंतिम पंक्ति की तरह कह सकते हैं।
बोहेमियन

यदि आप अपने एनम के लिए एक कस्टम लेबल चाहते हैं, तो अपने एनम वर्ग में स्ट्रीडिंग () को ओवरराइड करें।
राल्फगैब

क्या आप कृपया विस्फोट कर सकते हैं 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 बार कॉल क्यों करें ? इसके बजाय, जो अधिक उपयोग करने योग्य () का उपयोग क्यों करता है name()?
जेबी निज़ेट

@ जेबीएनज़ेट हेह, मैंने वास्तव में अपनी आईडीई में इस तरह की कोशिश की और आलसी को स्टेट व्यू बनाने के लिए मुझे लगता है कि, हेह, वैसे भी अब यह तय हो गया :)
PermGenError

2
आप अभी भी नाम नहीं लौटा रहे हैं, लेकिन स्ट्रींग () मान।
जेबी निज़ेट

@JBNizet हम्म, tbh, मैं वास्तव में पता है कि वहाँ एक name()विधि अब अनैतिक था । मुझे कितना बेवकूफ लगता है: पी मुझे धन्यवाद देने के लिए धन्यवाद :)
PermGenError

1
मैंने इस उत्तर को स्वीकार कर लिया, लेकिन मैंने एक संपादन प्रस्तुत किया जो कोड को बेहतर बनाता है इसलिए इसे पढ़ना आसान है।
कॉन्स्टेंटिन

14

यहाँ अपाचे कॉमन्स लैंग 3 का उपयोग कर एक सुंदर समाधान है :

EnumUtils.getEnumList(State.class)

हालाँकि यह एक सूची देता है, आप सूची को आसानी से बदल सकते हैं list.toArray()


5
EnumUtils.getEnumList(enumClass)एनम वैल्यूज लौटाता है, स्ट्रिंग्स नहीं। आप उपयोग कर सकते हैं EnumUtils.getEnumMap(enumClass).keySet(), लेकिन आदेश अलग हो सकता है।
डैन हैल्बर्ट

11

यदि आप Java 8 का उपयोग कर सकते हैं, तो यह अच्छी तरह से काम करता है (Yura के सुझाव का विकल्प, अधिक कुशल):

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

9

जावा 8 के साथ:

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

2
हालांकि यह संभवतः काम करता है, यह कार्यान्वयन काफी अक्षम है, पहले एक ArrayList बनाना, सभी तत्वों को जोड़ना, फिर एक सरणी बनाना और सब कुछ फिर से कॉपी करना।
डैनियल बिमछा 13

किसी भी समय जल्द ही "सभी" सबसे बुनियादी कार्यों को पूरा करने के लिए धाराओं का उपयोग करेंगे ... और यह बहुत अच्छा विचार नहीं है।
मार्कोलोप्स

इस तथ्य पर विचार करते हुए कि एनम में तत्वों की संख्या आमतौर पर छोटी है, मुझे लगता है कि यूरा का समाधान कई उपयोग के मामलों के लिए ठीक होगा। स्वाभाविक रूप से, यह विशिष्ट स्थिति पर निर्भर करेगा ...
स्टीफन.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
हालांकि यह विशेष रूप से कोई फर्क नहीं पड़ता है, लूप के लिए एक नियमित रूप से इस स्थिति में एक फॉर्च लूप की तुलना में बेहतर प्रदर्शन प्रदान करता है। इसके अलावा, values()दो बार कहा जाता है जब इसे केवल एक बार बुलाया जाना चाहिए।
FThompson

1
@Vulcan मुझे लगता है कि प्रदर्शन केवल इसके साथ एक मुद्दा होगा अगर इसे सैकड़ों हजारों बार चलाया गया। इसके अलावा, values()कंपाइलर द्वारा बनाई गई एक विधि है, इसलिए मुझे लगता है कि यह बहुत अनुकूलित है। अंत में, मुझे याद है कि कहीं-कहीं पढ़ने के लिए कि प्रत्येक लूप मानक से अधिक कुशल है, लूप के लिए वृद्धिशील, लेकिन फिर से - यह सिर्फ कोई फर्क नहीं पड़ता
कॉन्स्टेंटिन

@Konstantin यह विचार करते हुए कि जावा में फॉरेस्ट लूप को लूप के लिए एक मानक के साथ लागू किया जाता है, जहां आपने कभी पढ़ा कि फॉर्च लूप्स कभी अधिक कुशल होते हैं, गलत है।
ऋग्वेद

1
@ sage88 मैं उन छोरों के लिए जिक्र कर रहा था जिनमें आप एक संख्यात्मक सूचकांक का उपयोग करते हुए तत्वों को पुनः प्राप्त करते हैं, जिन्हें आप प्रत्येक चक्र में बढ़ाते हैं। उदाहरण के लिए: for (int i = 0; i < a.length; i++) /* do stuff */;इस मामले में, प्रत्येक लूप के लिए , वास्तव में, अधिक कुशल हैं। इस मामले पर एक त्वरित SO खोज हमें यह
Konstantin

@Konstantin किसी भी समय आपके पास एक डेटा संरचना होती है जो यादृच्छिक अभिगम की अनुमति देती है, जैसा कि एनम मूल्यों के साथ होता है, जो एक सरणी देता है, लूप के लिए सी-स्टाइल प्रत्येक लूप के लिए उपयोग करने से तेज है। प्रत्येक लूप के लिए एक इटरेटर उत्पन्न करना होता है, जो इसे धीमा बनाता है। आपके द्वारा पोस्ट किया गया लिंक प्राप्त (i) का उपयोग करके लिंक की गई सूची पर लूप के लिए एक मानक का उपयोग करने का एक उदाहरण देता है, जो निश्चित रूप से बदतर है। जब प्रत्येक लूप के लिए एक गैर-रैंडम एक्सेस डेटा संरचना का उपयोग किया जाता है, तो यह तेज होता है, लेकिन सरणियों पर इसका अधिक ओवरहेड होता है। इसके अलावा, चूंकि यह एक आदिम सरणी है, न कि एक ArrayList, इसलिए .size () से कोई प्रदर्शन हिट नहीं है।
sage88

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()अधिरोहित जा जा सकता है। एक स्ट्रिंग के रूप .name()में उदाहरण नाम प्राप्त करने के लिए मज़बूती से उपयोग करें ।
बोहेमियन

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(",");
    }
}

और जावा 7 आज्ञाकारी!
कुंभ राशि

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

और बस enum के अंदर एक स्टेटिक को परिभाषित करें ...

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

जावा एनम वास्तव में एक नाम () और प्राप्त (इंडेक्स) विधियों को याद करते हैं, वे वास्तव में सहायक हैं।


1

साधारण तरीका (सजा का इरादा):

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

1

मैंने @ बोहेमियन के समाधान पर थोड़ा परीक्षण किया। इसके बजाय भोले लूप का उपयोग करने पर प्रदर्शन बेहतर होता है।

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+ मान नहीं होंगे।
रौनी लिलेमेट्स


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

इसका दूसरा तरीका जावा 7 या उससे पहले का अमरूद का उपयोग करना होगा:

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नाम कहां है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.