जावा में स्ट्रिंग मान से एनम वैल्यू कैसे प्राप्त करें?


1982

कहो मेरे पास एक एनम है जो बस है

public enum Blah {
    A, B, C, D
}

और मैं एक स्ट्रिंग के एनम मान को खोजना चाहूंगा, उदाहरण के लिए "A"जो होगा Blah.A। ऐसा करना कैसे संभव होगा?

क्या Enum.valueOf()विधि मुझे चाहिए? यदि हां, तो मैं इसका उपयोग कैसे करूंगा?

जवाबों:


2258

हां, Blah.valueOf("A")आपको देंगे Blah.A

ध्यान दें कि नाम केस सहित एक सटीक मिलान होना चाहिए : Blah.valueOf("a")और Blah.valueOf("A ")दोनों एक फेंक देते हैं IllegalArgumentException

स्थिर तरीके valueOf()और values()संकलन समय पर बनाए जाते हैं और स्रोत कोड में दिखाई नहीं देते हैं। वे हालांकि, जावदोक में दिखाई देते हैं; उदाहरण के लिए, Dialog.ModalityTypeदोनों विधियों को दर्शाता है।


100
संदर्भ के लिए, Blah.valueOf("A")विधि संवेदनशील है और बाहरी व्हॉट्सएप को बर्दाश्त नहीं करती है, इस प्रकार @ JosMMi द्वारा प्रस्तावित वैकल्पिक समाधान है।
ब्रेट

3
@ मायकिल मायर्स, चूंकि यह उत्तर अब तक का सबसे अधिक मतदान है, तो क्या मुझे यह समझना चाहिए कि एक एनम को परिभाषित करने के लिए अच्छा अभ्यास है और इसका स्ट्रिंग मूल्य बिल्कुल समान है?
केविन मेरेडिथ

4
@KevinMeredith: यदि आप toString()मूल्य का मतलब है , नहीं, मैं यह नहीं कहूंगा। name()जब तक आप इसे ओवरराइड नहीं करते तब तक आपको एनम स्थिरांक का वास्तविक परिभाषित नाम मिलेगा।
माइकल मायर्स

3
आप वास्तव में "संकलन समय पर" बनाए गए हैं और स्रोत कोड में नहीं दिखाई देते हैं। ?
पेड़अरेवरी हर

8
@treesAreEverywhere अधिक विशेष रूप से, उन तरीकों को संकलक द्वारा उत्पन्न (या संश्लेषित ) किया जाता है। वास्तविक enum Blah {...}परिभाषा को अपनी valuesऔर न ही घोषित करने की कोशिश नहीं करनी चाहिए valuesOf। यह ऐसा है कि आप "AnyTypeName.class" कैसे लिख सकते हैं, भले ही आपने वास्तव में "वर्ग" सदस्य चर घोषित न किया हो; संकलक यह सब बस काम करता है। (यह उत्तर अब आपके लिए उपयोगी नहीं हो सकता है 3 महीने बाद, लेकिन सिर्फ मामले में।)
Ti Strga

864

एक और समाधान यदि पाठ एन्यूमरेशन मान के समान नहीं है:

public enum Blah {
    A("text1"),
    B("text2"),
    C("text3"),
    D("text4");

    private String text;

    Blah(String text) {
        this.text = text;
    }

    public String getText() {
        return this.text;
    }

    public static Blah fromString(String text) {
        for (Blah b : Blah.values()) {
            if (b.text.equalsIgnoreCase(text)) {
                return b;
            }
        }
        return null;
    }
}

396
throw new IllegalArgumentException("No constant with text " + text + " found")से बेहतर होगा return null
व्हिस्कीसिएर

8
@whiskeysierra जॉन स्कीट इससे सहमत नहीं होगा। stackoverflow.com/questions/1167982/…
सांग्युन ली

11
@Sangdol क्या आप हमें बता सकते हैं कि वापसी करना क्यों बेहतर है?
व्हिस्की सियार

57
@Sangdol आम तौर पर यह जांचने के लिए एक अच्छी बात है कि SUN - oops - Oracle एक ही स्थिति में क्या कर रहा है। और जैसा कि Enum.valueOf () दिखाया जा रहा है यह है सबसे अच्छा अभ्यास इस मामले में एक अपवाद फेंकने के लिए। क्योंकि यह एक असाधारण स्थिति है। "प्रदर्शन अनुकूलन" अपठनीय कोड लिखने के लिए एक बुरा बहाना है ;-)
raudi

5
ठीक है, आप इसे "पठनीय" बनाने के लिए @ निलेबल एनोटेशन का उपयोग भी कर सकते हैं; ;-)
जोसमी

121

यहाँ एक उपयोगी उपयोगिता है जिसका मैं उपयोग करता हूँ:

/**
 * A common method for all enums since they can't have another base class
 * @param <T> Enum type
 * @param c enum type. All enums must be all caps.
 * @param string case insensitive
 * @return corresponding enum, or null
 */
public static <T extends Enum<T>> T getEnumFromString(Class<T> c, String string) {
    if( c != null && string != null ) {
        try {
            return Enum.valueOf(c, string.trim().toUpperCase());
        } catch(IllegalArgumentException ex) {
        }
    }
    return null;
}

तब मेरे एनम वर्ग में आमतौर पर कुछ टाइपिंग को बचाने के लिए मेरे पास यह होता है:

public static MyEnum fromString(String name) {
    return getEnumFromString(MyEnum.class, name);
}

यदि आपके एनम सभी कैप नहीं हैं, तो बस Enum.valueOfलाइन बदलें ।

बहुत बुरा मैं उपयोग नहीं कर सकते T.classके लिए Enum.valueOfके रूप में Tमिटा दिया जाता है।


176
वह खाली कैच ब्लॉक वास्तव में मुझे पागल कर देता है, क्षमा करें।
व्हिस्कीसिएर

32
@LazloBonin: अपवाद असाधारण परिस्थितियों के लिए हैं, न कि नियंत्रण प्रवाह के लिए। अपने आप को प्रभावी जावा की एक प्रति प्राप्त करें ।
मोनिका को पुनः स्थापित करें - एम। श्रोडर

10
यदि जावा एपीआई आप एक अपवाद का उपयोग करना चाहते हैं और आप नहीं चाहते हैं कि आपका कोड एक को फेंक दे, तो आप या तो इस तरह के अपवाद को निगल सकते हैं, या स्क्रैच से तर्क को फिर से लिख सकते हैं, इसलिए कोई अपवाद पहली बार में नहीं फेंका जाता है। अपवाद को निगलने से अक्सर कम बुराई होती है।
नैट सीके

47
भयानक! हमेशा, हमेशा अपवादों को पकड़ें जहां आप उन्हें संभाल सकते हैं। ऊपर का उदाहरण एक आदर्श उदाहरण है कि यह कैसे नहीं करना है । क्यों? इसलिए यह NULL लौटाता है, और कॉल करने वाले को NULL के खिलाफ जांच करनी होती है या NPE फेंकनी होती है। यदि कॉल करने वाला जानता है कि स्थिति को कैसे संभालना है, तो अगर बनाम-कैच-कैच थोड़ा और सुरुचिपूर्ण लग सकता है, लेकिन अगर वह नहीं संभाल सकता है तो उसे फिर से पास करना होगा और कॉल करने वाले के कॉल को फिर से NULL के खिलाफ जांचना होगा , इत्यादि
राउडी

10
ऊपर दिए गए समाधान के लिए निष्पक्ष होने के लिए, वास्तव में ऐसे मामलों का उपयोग किया जाता है जो आपको अवैध तरीके से फेंकने के बजाय अवैध रूप से वापस जाने और अपने प्रोग्राम के प्रवाह को तोड़ने के लिए उपयोग करते हैं, उदाहरण के लिए, एक वेब सेवा स्कीमा और डेटाबेस स्कीमा के बीच एनमों की मैपिंग जिसमें वे हमेशा एक नहीं होते हैं -एक को। हालांकि, मैं मानता हूं कि कैच ब्लॉक को कभी खाली नहीं छोड़ा जाना चाहिए। ट्रैकिंग उद्देश्य के लिए कुछ कोड जैसे log.warn या कुछ डालें।
एड्रियन एम

101

जोशुआ बलोच, प्रभावी जावा से पैटर्न का उपयोग करें :

(संक्षिप्तता के लिए सरलीकृत)

enum MyEnum {
    ENUM_1("A"),
    ENUM_2("B");

    private String name;

    private static final Map<String,MyEnum> ENUM_MAP;

    MyEnum (String name) {
        this.name = name;
    }

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

    // Build an immutable map of String name to enum pairs.
    // Any Map impl can be used.

    static {
        Map<String,MyEnum> map = new ConcurrentHashMap<String, MyEnum>();
        for (MyEnum instance : MyEnum.values()) {
            map.put(instance.getName(),instance);
        }
        ENUM_MAP = Collections.unmodifiableMap(map);
    }

    public static MyEnum get (String name) {
        return ENUM_MAP.get(name);
    }
}

और देखें:

उदाहरण के Enum और मानचित्र का उपयोग करते हुए Oracle जावा उदाहरण

एक Enum प्रकार में स्थिर ब्लॉकों का निष्पादन क्रम

मैं अपने स्ट्रिंग मूल्य से जावा एनम कैसे देख सकता हूं


4
अगर यहोशू बलोच ने कहा, तो यह :-) जाने का एकमात्र तरीका है। इसकी शर्म की बात है कि मुझे हमेशा यहां स्क्रॉल करना पड़ता है।
डर्मोरिट्ज

11
यह जावा 8 में और भी सरल है जैसा कि आप कर सकते हैं: Stream.of(MyEnum.values()).collect(toMap(Enum::name, identity()))मैं भी ओवरराइडिंग () (कंस्ट्रक्टर के माध्यम से पारित) और नाम के बजाय इसका उपयोग करने की सलाह देता हूं, खासकर अगर Enum क्रमबद्ध डेटा के साथ जुड़ा हुआ है क्योंकि इससे आप बिना दिए गए कैसर को नियंत्रित कर सकते हैं। सोनार एक फिट।
Novaterata

1
जावा 8 निश्चित रूप से इस मंच पर बहुत सारे (बेहतर) उत्तरों को बदल सकता है। हालांकि, पूंछ (सोनार) के कुत्ते (एप्लिकेशन कोड) पर वैग होने के बारे में निश्चित नहीं है।
डेरेल टेग्यूग

3
यदि आप इसे किसी unmodifiableMapभी तरह से डालने जा रहे हैं , तो ए के साथ शुरू करने का कोई लाभ नहीं है ConcurrentHashMap। बस एक का उपयोग करें HashMap। (यदि आपके पास अमरूद है, ImmutableMapतो मैं इसके बजाय इसकी सलाह
दूंगा

9
स्थैतिक आरंभीकरण स्वाभाविक रूप से सिंक्रनाइज़ है , इसलिए ConcurrentHashMapयहां उपयोग करने का कोई कारण नहीं है, जहां मानचित्र को आरंभीकरण के बाद कभी भी संशोधित नहीं किया जाता है। इसलिए भी उदाहरण के लिए जेएलएस में ही उदाहरण एक नियमित का उपयोग करता है HashMap
रेडियोडफ

74

आपको अपने मामले से भी सावधान रहना चाहिए। मुझे समझाने दो: Blah.valueOf("A")काम कर रहा है, लेकिन Blah.valueOf("a")काम नहीं करेगा। फिर Blah.valueOf("a".toUpperCase(Locale.ENGLISH))काम करेगा।

संपादित
बदल दिया toUpperCaseकरने toUpperCase(Locale.ENGLISH)के आधार पर टीसी। टिप्पणी और जावा डॉक्स

EDIT2 पर आप का उपयोग करना चाहिए android Locale.USके रूप में, sulai बताते हैं


6
डिफ़ॉल्ट लोकेल से सावधान रहें!
टीसी

3
आपके लिए एंड्रॉइड उपयोगकर्ता वहां से बाहर निकलना चाहते हैं, मैं यह बताना चाहता हूं कि एंड्रॉइड प्रलेखन स्पष्ट रूप से Locale.USमशीन पठनीय इनपुट / आउटपुट के उपयोग को प्रोत्साहित करता है ।
सुलाय

2
@ टेंगोट हां, दुर्भाग्य से। तुर्की एक अच्छा उदाहरण है। इसे डिफ़ॉल्ट चार्ट्स के जावा के टूटे हुए हैंडलिंग (यूनिकोड के बजाय विंडोज पर लैटिन में चूक) के साथ मिलाएं और आप पाएंगे कि यह हमेशा उन तरीकों के डिफ़ॉल्ट संस्करणों का उपयोग करने के लिए असुरक्षित है जो एक चार्टसेट या लोकेल को स्वीकार करते हैं। आपको लगभग हमेशा उन्हें स्पष्ट रूप से परिभाषित करना चाहिए।
स्टिज डे विट

सुनिश्चित नहीं है कि जावा के "डिफ़ॉल्ट" चारसेट एट अल "प्रति टूटे हुए" हैं, लेकिन प्रदान किए गए हैं, ओवरराइड्स के बदले UTF-8 के लिए डिफ़ॉल्ट (जो हमेशा स्पष्ट होना चाहिए) ने जूनियर प्रोग्रामर के लिए बेहतर सिस्टम बना दिया होगा जो आमतौर पर समझने में विफल होते हैं। चारसेट अवधारणाएँ।
डेरेल टेग्यू

38

यहाँ एक विधि है जो इसे किसी भी Enum के लिए कर सकती है, और यह असंवेदनशील है।

/** 
 * Finds the value of the given enumeration by name, case-insensitive. 
 * Throws an IllegalArgumentException if no match is found.  
 **/
public static <T extends Enum<T>> T valueOfIgnoreCase(
        Class<T> enumeration, String name) {

    for (T enumValue : enumeration.getEnumConstants()) {
        if (enumValue.name().equalsIgnoreCase(name)) {
            return enumValue;
        }
    }

    throw new IllegalArgumentException(String.format(
        "There is no value with name '%s' in Enum %s",
        name, enumeration.getName()
    ));
}

यह भिन्नता इसे सही ढंग से कर रही है: equalsIgnoreCaseजाने का रास्ता है। +1
स्टिज डे विट

मामले की असंवेदनशीलता की तरह लेकिन ... एनम को प्राथमिकता दें (यादृच्छिक) कुंजी के लिए स्ट्रिंग असाइनमेंट और ... नाबालिग लेकिन इस तरह के दोहराए जाने वाले लुकअप के लिए पुनरावृत्ति कम प्रदर्शन है। इसलिए EnumMap एट अल के निहित है।
डेरेल टेग्यूग

यह काम नहीं करता ! मैंने अपने उद्देश्य के लिए equalsIgnoreCase को बराबर में बदल दिया। कोड विफल हो गया, हालांकि दोनों इनपुट समान हैं, बिल्कुल समान थे।
मास्टर जियो 2

36

का उपयोग करना Blah.valueOf(string)सबसे अच्छा है लेकिन आप भी उपयोग कर सकते हैं Enum.valueOf(Blah.class, string)


1
संवेदनशील मामला, मदद नहीं!
मुर्तजा कांचवाला

@ मुर्तजाकांचवाला क्या आप अपनी टिप्पणी स्पष्ट कर सकते हैं? तुम क्या करने की कोशिश कर रहे हो?
पीटर लॉरी

2
Hi @PeterLawrey, मैं एक स्ट्रिंग को सार्वजनिक पब्लिक एनम ऑब्जेक्टटाइप {PERSON ("व्यक्ति") सार्वजनिक स्ट्रिंग पैरामीटर नाम से एक एनम लाने के लिए ट्रिंग कर रहा था; ObjectType (स्ट्रिंग पैरामीटर नाम) {this.parameterName = पैरामीटर नाम; } सार्वजनिक स्ट्रिंग getParameterName () {यह लौटाएं। पैरामीटर नाम; } public static ObjectType fromString (स्ट्रिंग पैरामीटर नाम) {if (पैरामीटरName! = null) {for (ObjectType objType: ObjectType.values ​​()) {if (पैरामीटरName.equals.gnoreCase (objType.parameterName)) {वापसी objType; }}} वापसी अशक्त; }}
मुर्तजा कांचवाला

34

जावा 8 या बाद में, स्ट्रीम का उपयोग करते हुए :

public enum Blah
{
    A("text1"),
    B("text2"),
    C("text3"),
    D("text4");

    private String text;

    Blah(String text) {
        this.text = text;
    }

    public String getText() {
        return this.text;
    }

    public static Optional<Blah> fromText(String text) {
        return Arrays.stream(values())
          .filter(bl -> bl.text.equalsIgnoreCase(text))
          .findFirst();
    }
}

यकीन नहीं होता कि यह किसी भी तरह से एक बेहतर जवाब है। इस मामले में धाराएं सभी मानों पर किसी भी अन्य की तरह एक एकल-थ्रेडेड इट्रेटर हैं और यकीनन मानचित्र लुकअप की तुलना में कम प्रदर्शनकारी हैं। एक बहु-थ्रेडेड संदर्भ में धाराओं का अधिक मूल्य होता है, उदाहरण के लिए, एक नईलाइन-अलग-अलग पाठ फ़ाइल के समानांतर निष्पादन से प्रदर्शन में सुधार हो सकता है।
डेरेल टीग ने

28

यदि आप अपनी उपयोगिता लिखने के लिए Google का उपयोग नहीं करना चाहते हैं पुस्तकालय:

Enums.getIfPresent(Blah.class, "A")

बिल्ट इन जावा फंक्शन के विपरीत, आइए हम जांचते हैं कि क्या ए ब्लाह में मौजूद है और कोई अपवाद नहीं है।


7
दुखद बात यह है, यह एक Google वैकल्पिक रिटर्न देता है और जावा वैकल्पिक नहीं
javaProgrammer

सच। हालांकि समाप्त हो गया। Google और नेटफ्लिक्स के पास जावा के बहुत अच्छे काम हैं। जहां नए संस्करणों में कार्यान्वित जावा कैच-अप कक्षाओं के साथ ओवरलैप होना अनिवार्य रूप से परेशानी का कारण बनता है। एक विक्रेता के दायित्व में सभी तरह का होना चाहिए।
डेरेल टीगू

26

मेरे 2 सेंट यहाँ: Java8 स्ट्रीम का उपयोग करके + एक सटीक स्ट्रिंग की जाँच:

public enum MyEnum {
    VALUE_1("Super"),
    VALUE_2("Rainbow"),
    VALUE_3("Dash"),
    VALUE_3("Rocks");

    private final String value;

    MyEnum(String value) {
        this.value = value;
    }

    /**
     * @return the Enum representation for the given string.
     * @throws IllegalArgumentException if unknown string.
     */
    public static MyEnum fromString(String s) throws IllegalArgumentException {
        return Arrays.stream(MyEnum.values())
                .filter(v -> v.value.equals(s))
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException("unknown value: " + s));
    }
}

** EDIT **

fromString()उस कन्वेंशन का नामकरण करने के बाद से फ़ंक्शन का नाम दिया गया है, आपको जावा भाषा से ही कुछ लाभ मिलेंगे; उदाहरण के लिए:

  1. हेडरपरम एनोटेशन में प्रकारों का प्रत्यक्ष रूपांतरण

1
वैकल्पिक रूप से आपको अधिक पठनीय switchब्लॉक लिखने की अनुमति देने के लिए , आप .orElse(null)इसके बजाय, .orElseThrow()ताकि आप defaultक्लॉज में अपवाद फेंक को कोड कर सकें - और आवश्यकता पड़ने पर अधिक उपयोगी जानकारी शामिल कर सकें । और इसे और अधिक उदार बनाने के लिए आप उपयोग कर सकते हैंv -> Objects.equals(v.name, s == null ? "" : s.trim().toUpperCase())
एडम

या सिर्फ लौटने Optionalसे findFirst(), वह चाहता है, तो उपयोगकर्ता को यह तय करने की इजाजत दी .orElse(null), orElseThrow()या जो कुछ भी ....
user85421

1
घोषणा public static MyEnum valueOf(String)करना वास्तव में एक संकलन त्रुटि है, क्योंकि यह एक समान रूप से परिभाषित है, इसलिए आपके उत्तर का पुराना संस्करण वास्तव में बेहतर है। ( jls , ideone )
रेडियोडेफ

मेरे विकल्प में अपवादों से बचना और वैकल्पिक उपयोग करना बेहतर है। इसके आगे हमें शून्य को शून्य करना चाहिए और साथ ही वैकल्पिक का उपयोग करना चाहिए।
हंस श्रुडर

फिर से, बस याद रखें कि भले ही कम या बेहतर दिखने वाला कोड ... इस तरह एक स्ट्रीम कार्यान्वयन सभी मानों पर एक नक्शे के लुकअप (कम प्रदर्शन करने वाले) के बजाय सिर्फ एक पुनरावृत्ति है।
डेरेल टेग्यूज

16

आपको इसकी आवश्यकता हो सकती है:

public enum ObjectType {
    PERSON("Person");

    public String parameterName;

    ObjectType(String parameterName) {
        this.parameterName = parameterName;
    }

    public String getParameterName() {
        return this.parameterName;
    }

    //From String method will return you the Enum for the provided input string
    public static ObjectType fromString(String parameterName) {
        if (parameterName != null) {
            for (ObjectType objType : ObjectType.values()) {
                if (parameterName.equalsIgnoreCase(objType.parameterName)) {
                    return objType;
                }
            }
        }
        return null;
    }
}

एक और अतिरिक्त:

   public static String fromEnumName(String parameterName) {
        if (parameterName != null) {
            for (DQJ objType : DQJ.values()) {
                if (parameterName.equalsIgnoreCase(objType.name())) {
                    return objType.parameterName;
                }
            }
        }
        return null;
    }

यह आपको स्ट्रिंग नामांकित नाम से मान लौटाएगा जैसे कि यदि आप fromEnumName में "PERSON" प्रदान करते हैं तो यह आपको Enum का मान लौटाएगा अर्थात "व्यक्ति"


13

name()Enum के निहित स्थिर विधि का उपयोग करके ऐसा करने का दूसरा तरीका । नाम उस एनम को बनाने के लिए उपयोग की जाने वाली सटीक स्ट्रिंग को लौटाएगा जिसका उपयोग प्रदान किए गए स्ट्रिंग के खिलाफ जांच करने के लिए किया जा सकता है:

public enum Blah {

    A, B, C, D;

    public static Blah getEnum(String s){
        if(A.name().equals(s)){
            return A;
        }else if(B.name().equals(s)){
            return B;
        }else if(C.name().equals(s)){
            return C;
        }else if (D.name().equals(s)){
            return D;
        }
        throw new IllegalArgumentException("No Enum specified for this string");
    }
}

परिक्षण:

System.out.println(Blah.getEnum("B").name());

//it will print B  B

प्रेरणा: जावा में Enum के 10 उदाहरण


7
यह अनिवार्य रूप से valueOfआपके लिए क्या करता है। यह स्थिर विधि कुछ भी अतिरिक्त, अपवाद एट सभी की पेशकश नहीं करती है। तब यदि / अन्यथा निर्माण अत्यधिक खतरनाक होते हैं ... कोई भी नई ईनम निरंतर जोड़ी बिना बदलाव के इस पद्धति को तोड़ देगी।
योयो

इस उदाहरण पर भी विचार करें कि हम किसी मामले को असंवेदनशील देखने के लिए valueOf का उपयोग कैसे कर सकते हैं, या हम इसे कैसे छोड़ सकते हैं और वैकल्पिक नामों को प्रदान करने के लिए उपनामों को नियोजित कर सकते हैं: stackoverflow.com/a/12659023/744133
YoYo

2
name()स्थिर नहीं है।
nrubin29

10

अमरूद पुस्तकालयों का उपयोग कर समाधान। विधि getPlanet () स्थिति असंवेदनशील है, इसलिए getPlanet ("MerCUrY") Planet.MERCURY वापस आ जाएगी।

package com.universe.solarsystem.planets;
import org.apache.commons.lang3.StringUtils;
import com.google.common.base.Enums;
import com.google.common.base.Optional;

//Pluto and Eris are dwarf planets, who cares!
public enum Planet {
   MERCURY,
   VENUS,
   EARTH,
   MARS,
   JUPITER,
   SATURN,
   URANUS,
   NEPTUNE;

   public static Planet getPlanet(String name) {
      String val = StringUtils.trimToEmpty(name).toUpperCase();
      Optional <Planet> possible = Enums.getIfPresent(Planet.class, val);
      if (!possible.isPresent()) {
         throw new IllegalArgumentException(val + "? There is no such planet!");
      }
      return possible.get();
   }
}

8

पिछले उत्तरों में जोड़ने के लिए, और nulls और NPE के आस-पास कुछ चर्चाओं को संबोधित कर रहा हूँ जो मैं अनुपस्थित / अमान्य मामलों को संभालने के लिए Guava Optionals का उपयोग कर रहा हूँ। यह यूआरआई / पैरामीटर पार्सिंग के लिए बहुत अच्छा काम करता है।

public enum E {
    A,B,C;
    public static Optional<E> fromString(String s) {
        try {
            return Optional.of(E.valueOf(s.toUpperCase()));
        } catch (IllegalArgumentException|NullPointerException e) {
            return Optional.absent();
        }
    }
}

जिन लोगों को जानकारी नहीं है, उनके लिए वैकल्पिक के साथ अशक्तता से बचने के बारे में कुछ और जानकारी: https://code.google.com/p/guava-lbooks/wiki/UsingAndAvoidingNullExplained#Optional


यह एक Enum के अंदर संबंधित पैटर्न और वैकल्पिक के उपयोग के लिए एक बहुत अच्छा जवाब है - इस तथ्य का लाभ उठाते हुए कि Enums कक्षाएं भी हैं और इस तरह तरीकों, ओवरराइड विधियों, आदि के साथ सजाया जा सकता है, यह फ़्लुएंट-स्टाइल प्रोग्रामिंग के लिए भी एक अच्छा मामला है। तरीकों से लौटाए गए नल, बगगी का निर्माण करते हैं (विधि कॉल के धाराप्रवाह श्रृंखला में अज्ञात स्थानों में एनपीई)।
डारेल टीगूज

8

जावा 8 में स्थैतिक मानचित्र पैटर्न और भी आसान है और यह मेरी पूर्वनिर्मित विधि है। यदि आप जैक्सन के साथ एनम का उपयोग करना चाहते हैं, तो आप स्ट्रीडिंग को ओवरराइड कर सकते हैं और नाम के बजाय इसका उपयोग कर सकते हैं, तो एनोटेट के साथ@JsonValue

public enum MyEnum {
    BAR,
    BAZ;
    private static final Map<String, MyEnum> MAP = Stream.of(MyEnum.values()).collect(Collectors.toMap(Enum::name, Function.identity()));
    public static MyEnum fromName(String name){
        return MAP.get(name);
    }
}

public enum MyEnumForJson {
    BAR("bar"),
    BAZ("baz");
    private static final Map<String, MyEnumForJson> MAP = Stream.of(MyEnumForJson.values()).collect(Collectors.toMap(Object::toString, Function.identity()));
    private final String value;

    MyEnumForJson(String value) {
        this.value = value;
    }

    @JsonValue
    @Override
    public String toString() {
        return value;
    }

    public static MyEnumForJson fromValue(String value){
        return MAP.get(value);
    }
}

जैक्सन एक JSON (जावास्क्रिप्ट ऑब्जेक्ट नोटेशन) कार्यान्वयन है। मूल प्रश्न का JSON से कोई लेना-देना नहीं था।
डेरेल टेग्यूज

JSON का हिस्सा सिर्फ बोनस सामान था जो मुझे उस समय प्रासंगिक लगा, क्योंकि एक स्ट्रिंग से Enum प्राप्त करना मूल रूप से एक प्रकार का डीज़रीलाइज़ेशन है और JSON / जैक्सन शायद सबसे लोकप्रिय क्रमांकन समाधान है।
नवतारा

समझें, लेकिन मॉडरेशन पहलू से - यह ओपी के सवाल का जवाब देने में योगदान नहीं करता है, इसलिए बस वहां संदर्भ सेट करने में मदद करने की कोशिश कर रहा है। जेन्सन वास्तव में जावा में एक महान पुस्तकालय होने के साथ वस्तुओं को जावा में विहित रूप में परिवर्तित करने का रास्ता है।
डैरेल टीग्यूज

6
public static MyEnum getFromValue(String value) {
    MyEnum resp = null;
    MyEnum nodes[] = values();
    for(int i = 0; i < nodes.length; i++) {
        if(nodes[i].value.equals(value)) {
            resp = nodes[i];
            break;
        }
    }
    return resp;
}

stackoverflow.com पर प्रश्नों के उत्तर देने और पूछने के लिए गाइड के इस लिंक पर एक नज़र डालें: stackoverflow.com/faq
bakoyaro

1
यही कारण है कि जोसेमी के जवाब के रूप में कम या ज्यादा ही है
Rup

6

हे (1) विधि थ्रोट जनरेट कोड से प्रेरित है जो हैशमैप का उपयोग करता है।

public enum USER {
        STUDENT("jon",0),TEACHER("tom",1);

        private static final Map<String, Integer> map = new HashMap<>();

        static {
                for (USER user : EnumSet.allOf(USER.class)) {
                        map.put(user.getTypeName(), user.getIndex());
                }
        }

        public static int findIndexByTypeName(String typeName) {
                return map.get(typeName);
        }

        private USER(String typeName,int index){
                this.typeName = typeName;
                this.index = index;
        }
        private String typeName;
        private int index;
        public String getTypeName() {
                return typeName;
        }
        public void setTypeName(String typeName) {
                this.typeName = typeName;
        }
        public int getIndex() {
                return index;
        }
        public void setIndex(int index) {
                this.index = index;
        }

}

नोट शून्य (0) और एक (1) पहचानकर्ता अनावश्यक हैं। Enum मान () विधि सदस्यों को उसी क्रम में लौटाएगी जो कोडित है। इस प्रकार पहली प्रविष्टि क्रमिक शून्य, दूसरी एक आदि होगी
डारेल टीग

6

एनम बहुत उपयोगी है, मैं Enumविभिन्न भाषाओं में कुछ क्षेत्रों के लिए विवरण जोड़ने के लिए बहुत उपयोग कर रहा हूं , निम्न उदाहरण के रूप में:

public enum Status {

    ACT(new String[] { "Accepted", "مقبول" }),
    REJ(new String[] { "Rejected", "مرفوض" }),
    PND(new String[] { "Pending", "في الانتظار" }),
    ERR(new String[] { "Error", "خطأ" }),
    SNT(new String[] { "Sent", "أرسلت" });

    private String[] status;

    public String getDescription(String lang) {
        return lang.equals("en") ? status[0] : status[1];
    }

    Status(String[] status) {
        this.status = status;
    }
}

और फिर आप getDescription(String lang)उदाहरण के लिए, विधि के लिए पारित भाषा कोड में गतिशील रूप से विवरण प्राप्त कर सकते हैं :

String statusDescription = Status.valueOf("ACT").getDescription("en");

1
एनम को और आगे बढ़ाने के साथ अच्छा उदाहरण। मानक स्थैतिक नाम और मैप में लुकअप का उपयोग करके भाषा-एन्कोडिंग बना होगा, लेकिन फिर भी ... जो आवश्यक रूप से समान तार्किक मूल्य के लिए अलग-अलग टैग के साथ एक एनुम होने का एक अच्छा उदाहरण है।
डेरेल टीग

5

व्हाट अबाउट?

public enum MyEnum {
    FIRST,
    SECOND,
    THIRD;

    public static Optional<MyEnum> fromString(String value){
        try{
            return Optional.of(MyEnum.valueOf(value));
        }catch(Exception e){
            return Optional.empty();
        }
    }
}

4

java.lang.Enum कई उपयोगी तरीकों को परिभाषित करता है, जो जावा में सभी एन्यूमरेशन प्रकार के लिए उपलब्ध है:

  • आप उपयोग कर सकते हैं name() किसी भी Enum स्थिरांक का नाम प्राप्त करने के लिए विधि का । Enum constants लिखने के लिए इस्तेमाल किया जाने वाला स्ट्रिंग शाब्दिक नाम है।
  • उसी प्रकार values() एक Enum प्रकार से सभी Enum स्थिरांक की एक सरणी प्राप्त करने के लिए विधि का उपयोग किया जा सकता है।
  • और पूछे गए प्रश्न के लिए, आप valueOf()किसी भी स्ट्रिंग को जावा में Enum स्थिरांक में बदलने के लिए विधि का उपयोग कर सकते हैं , जैसा कि नीचे दिखाया गया है।
public class EnumDemo06 {
    public static void main(String args[]) {
        Gender fromString = Gender.valueOf("MALE");
        System.out.println("Gender.MALE.name() : " + fromString.name());
    }

    private enum Gender {
        MALE, FEMALE;
    }
}

Output:
Gender.MALE.name() : MALE

इस कोड स्निपेट में, valueOf()विधि एक Enum निरंतर Gender.MALE लौटाती है, जो उस रिटर्न पर कॉलिंग नाम है "MALE"


4

अपाचे के कॉमन्स-लैंग लाइब्रेरी में स्टैटिक फंक्शन org.apache.commons.lang3.EnumUtils.getEnum है जो आपके Enum टाइप करने के लिए एक स्ट्रिंग को मैप करेगा। अनिवार्य रूप से Geoffreys के रूप में एक ही जवाब है, लेकिन क्यों अपने खुद के रोल जब यह वहाँ पहले से ही जंगली में है।


1
निष्पक्ष टिप्पणी (DRY) लेकिन ... जबकि अपाचे कॉमन्स सामान में से अधिकांश महान है, मैंने उस आधार में कई बग और विरोधी पैटर्न खुद को पाया है। इस प्रकार यह कहते हुए कि यहोशू बलोच का क्रियान्वयन और मजबूत हो सकता है। यह जानने के लिए कि किसी ने क्या लागू किया है, अपाचे कोड की समीक्षा करने के लिए नीचे जाता है। अगर यह कहा जाता है कि प्रसिद्ध डौग लीह ने जावा कॉन्क्वेरी को फिर से लिखा था ... तो मुझे इस पर भरोसा होगा।
डेरेल टेग्यूज

4

एक उपयोगी उपयोगिता के साथ शीर्ष रेटेड उत्तर में जोड़ना ...

valueOf() उन मामलों में दो अलग-अलग अपवादों को फेंकता है जहां यह अपने इनपुट को पसंद नहीं करता है।

  • IllegalArgumentException
  • NullPointerExeption

यदि आपकी आवश्यकताएं ऐसी हैं कि आपके पास कोई गारंटी नहीं है कि आपका स्ट्रिंग निश्चित रूप से एनम मूल्य से मेल खाएगा, उदाहरण के लिए यदि स्ट्रिंग डेटा डेटाबेस से आता है और इसमें एनम का पुराना संस्करण हो सकता है, तो आपको इन्हें संभालने की आवश्यकता होगी अक्सर ...

तो यहाँ एक पुन: प्रयोज्य विधि मैंने लिखी है जो हमें एक डिफ़ॉल्ट Enum को परिभाषित करने की अनुमति देती है यदि स्ट्रिंग हम पास नहीं करते हैं तो मिलान नहीं होता है।

private static <T extends Enum<T>> T valueOf( String name , T defaultVal) {
        try {
            return Enum.valueOf(defaultVal.getDeclaringClass() , name);
        } catch (IllegalArgumentException | NullPointerException e) {
            return defaultVal;
        }
    }

इसे इस तरह उपयोग करें:

public enum MYTHINGS {
    THINGONE,
    THINGTWO
}

public static void main(String [] asd) {
  valueOf("THINGTWO" , MYTHINGS.THINGONE);//returns MYTHINGS.THINGTWO
  valueOf("THINGZERO" , MYTHINGS.THINGONE);//returns MYTHINGS.THINGONE
}

2

के रूप में switch-version का उल्लेख अभी तक नहीं किया गया है, मैं इसे शुरू करता हूं (ओप्स एनम का पुन: उपयोग):

  private enum Blah {
    A, B, C, D;

    public static Blah byName(String name) {
      switch (name) {
        case "A":
          return A;
        case "B":
          return B;
        case "C":
          return C;
        case "D":
          return D;
        default:
          throw new IllegalArgumentException(
            "No enum constant " + Blah.class.getCanonicalName() + "." + name);
      }
    }
  }

चूँकि यह valueOf(String name)विधि को कोई अतिरिक्त मूल्य नहीं देता है , यह केवल एक अतिरिक्त विधि को परिभाषित करने के लिए समझ में आता है अगर हम एक अलग व्यवहार चाहते हैं। यदि हम नहीं उठाना चाहते हैं तो IllegalArgumentExceptionहम कार्यान्वयन को बदल सकते हैं:

  private enum Blah {
    A, B, C, D;

    public static Blah valueOfOrDefault(String name, Blah defaultValue) {
      switch (name) {
        case "A":
          return A;
        case "B":
          return B;
        case "C":
          return C;
        case "D":
          return D;
        default:
          if (defaultValue == null) {
            throw new NullPointerException();
          }
          return defaultValue;
      }
    }
  }

एक डिफ़ॉल्ट मूल्य प्रदान करके हम उस तरीके से बिना किसी अनुबंध के Enum.valueOf(String name)फेंक IllegalArgumentExceptionदेते हैं कि किसी भी स्थिति nullमें वापस नहीं किया जाता है। इसलिए हम फेंक देते हैं NullPointerExceptionयदि नाम है nullऔर defaultयदि defaultValueहै तो null। कि कैसेvalueOfOrDefault काम करता है।

यह दृष्टिकोण -इंटरफेस के डिज़ाइन को अपनाता है Mapजो Map.getOrDefault(Object key, V defaultValue)जावा 8 के रूप में एक विधि प्रदान करता है ।


1

एक और उपयोगिता उल्टे तरीके से कैप्चर करना। एक मान का उपयोग करना जो उस एनम की पहचान करता है, उसके नाम से नहीं।

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.EnumSet;

public class EnumUtil {

    /**
     * Returns the <code>Enum</code> of type <code>enumType</code> whose a 
     * public method return value of this Enum is 
     * equal to <code>valor</code>.<br/>
     * Such method should be unique public, not final and static method 
     * declared in Enum.
     * In case of more than one method in match those conditions
     * its first one will be chosen.
     * 
     * @param enumType
     * @param value
     * @return 
     */
    public static <E extends Enum<E>> E from(Class<E> enumType, Object value) {
        String methodName = getMethodIdentifier(enumType);
        return from(enumType, value, methodName);
    }

    /**
     * Returns the <code>Enum</code> of type <code>enumType</code> whose  
     * public method <code>methodName</code> return is 
     * equal to <code>value</code>.<br/>
     *
     * @param enumType
     * @param value
     * @param methodName
     * @return
     */
    public static <E extends Enum<E>> E from(Class<E> enumType, Object value, String methodName) {
        EnumSet<E> enumSet = EnumSet.allOf(enumType);
        for (E en : enumSet) {
            try {
                String invoke = enumType.getMethod(methodName).invoke(en).toString();
                if (invoke.equals(value.toString())) {
                    return en;
                }
            } catch (Exception e) {
                return null;
            }
        }
        return null;
    }

    private static String getMethodIdentifier(Class<?> enumType) {
        Method[] methods = enumType.getDeclaredMethods();
        String name = null;
        for (Method method : methods) {
            int mod = method.getModifiers();
            if (Modifier.isPublic(mod) && !Modifier.isStatic(mod) && !Modifier.isFinal(mod)) {
                name = method.getName();
                break;
            }
        }
        return name;
    }
}

उदाहरण:

public enum Foo {
    ONE("eins"), TWO("zwei"), THREE("drei");

    private String value;

    private Foo(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}

EnumUtil.from(Foo.class, "drei")रिटर्न Foo.THREE, क्योंकि यह getValue"ड्रि" से मेल खाने के लिए उपयोग करेगा , जो कि अद्वितीय सार्वजनिक है, अंतिम नहीं है और फू में स्थिर विधि नहीं है। यदि फू में सार्वजनिक से अधिक है, तो अंतिम नहीं और स्थिर विधि नहीं है, उदाहरण के लिए, getTranslateजो "drei" लौटाता है, दूसरी विधि का उपयोग किया जा सकता है EnumUtil.from(Foo.class, "drei", "getTranslate"):।


1

कोटलिन समाधान

एक एक्सटेंशन बनाएं और फिर कॉल करें valueOf<MyEnum>("value")। यदि प्रकार अमान्य है, तो आपको अशक्त हो जाएगा और इसे संभालना होगा

inline fun <reified T : Enum<T>> valueOf(type: String): T? {
    return try {
        java.lang.Enum.valueOf(T::class.java, type)
    } catch (e: Exception) {
        null
    }
}

वैकल्पिक रूप से, आप एक डिफ़ॉल्ट मान सेट कर सकते हैं, कॉल कर सकते हैं valueOf<MyEnum>("value", MyEnum.FALLBACK), और अशक्त प्रतिक्रिया से बच सकते हैं। डिफ़ॉल्ट होने के लिए आप अपने विशिष्ट एनम का विस्तार कर सकते हैं स्वचालित

inline fun <reified T : Enum<T>> valueOf(type: String, default: T): T {
    return try {
        java.lang.Enum.valueOf(T::class.java, type)
    } catch (e: Exception) {
        default
    }
}

या यदि आप दोनों चाहते हैं, तो दूसरा बनाएं:

inline fun <reified T : Enum<T>> valueOf(type: String, default: T): T = valueOf<T>(type) ?: default

क्या आपको लगता है कि आपके जवाब में यहां एक बेहतर घर होगा? stackoverflow.com/questions/28548015/…
nabster

0

मैं इस तरह की प्रक्रिया का उपयोग करने के लिए गणना में तार के रूप में आदेशों को पार्स करना पसंद करता हूं। मेरे पास सामान्य रूप से "अज्ञात" के रूप में गणना में से एक है, इसलिए यह उस स्थिति में मदद करता है जब दूसरों को नहीं मिला है (भले ही असंवेदनशील आधार पर) शून्य के बजाय (जिसका अर्थ है कि कोई मूल्य नहीं है)। इसलिए मैं इस दृष्टिकोण का उपयोग करता हूं।

static <E extends Enum<E>> Enum getEnumValue(String what, Class<E> enumClass) {
    Enum<E> unknown=null;
    for (Enum<E> enumVal: enumClass.getEnumConstants()) {  
        if (what.compareToIgnoreCase(enumVal.name()) == 0) {
            return enumVal;
        }
        if (enumVal.name().compareToIgnoreCase("unknown") == 0) {
            unknown=enumVal;
        }
    }  
    return unknown;
}

-1

एनम का नाम पाने के लिए सबसे तेज़ तरीका है कि एनुम टेक्स्ट और वैल्यू का एक नक्शा बनाएं जब एप्लिकेशन शुरू हो, और नाम पाने के लिए फ़ंक्शन को कॉल करें Blah.getEnumName ():

public enum Blah {
    A("text1"),
    B("text2"),
    C("text3"),
    D("text4");

    private String text;
    private HashMap<String, String> map;
    Blah(String text) {
    this.text = text;
    }

    public String getText() {
      return this.text;
    }

    static{
      createMapOfTextAndName();
    }

    public static void createMapOfTextAndName() {
        map = new HashMap<String, String>();
        for (Blah b : Blah.values()) {
             map.put(b.getText(),b.name());
        }
    }
    public static String getEnumName(String text) {
        return map.get(text.toLowerCase());
    } 
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.