जावा: जांचें कि क्या एनम में एक दिया स्ट्रिंग है?


169

यहाँ मेरी समस्या है - मैं तलाश कर रहा हूँ (अगर यह मौजूद है) तो एनम के बराबर है ArrayList.contains();

यहाँ मेरी कोड समस्या का एक नमूना है:

enum choices {a1, a2, b1, b2};

if(choices.???(a1)}{
//do this
} 

अब, मुझे लगता है कि एक ArrayListका Stringsबेहतर मार्ग यहाँ होगा, लेकिन मैं कहीं और एक स्विच / मामले के माध्यम से अपने enum सामग्री को चलाने के लिए है। इसलिए मेरी समस्या।

कुछ इस तरह मौजूद नहीं है, मैं इसे कैसे कर सकता हूँ?


स्विच / केस स्ट्रिंग्स के साथ जावा 7 से शुरू होता है
एंड्रीपी

जवाबों:


205

यह करना चाहिए:

public static boolean contains(String test) {

    for (Choice c : Choice.values()) {
        if (c.name().equals(test)) {
            return true;
        }
    }

    return false;
}

इस तरह से इसका मतलब है कि आपको बाद में अतिरिक्त एनम मूल्यों को जोड़ने के बारे में चिंता करने की ज़रूरत नहीं है, वे सभी चेक किए गए हैं।

संपादित करें: यदि एनम बहुत बड़ी है तो आप हाशसेट में मान चिपका सकते हैं:

public static HashSet<String> getEnums() {

  HashSet<String> values = new HashSet<String>();

  for (Choice c : Choice.values()) {
      values.add(c.name());
  }

  return values;
}

तब आप बस कर सकते हैं: values.contains("your string")जो सही या गलत है।


12
यह बहुत ही घटिया घटना है। Choice.valueOf (परीक्षण) आप क्या चाहते हैं (w / कोशिश / पकड़)
bestsss

17
bestsss, यह स्पष्ट रूप से सबसे उपयुक्त समाधान है। एक प्रकार के अस्तित्व को लागू करने के लिए एक अपवाद को फेंकना () विधि खराब अभ्यास है। हालांकि आप सोच सकते हैं कि ओ (एन) नहीं लगने के कारण आपका कार्यान्वयन अधिक कुशल है, यह अंतर्निहित ढांचे में है जो दिखाई नहीं देता है। इसके अलावा प्रयास {} कैच का उपयोग ओवरहेड जोड़ता है। इसके अलावा, यह सिर्फ सुंदर नहीं है।
jluzwick

25
@ जरूर, जरूर देखें। बस अपने अपवाद को पकड़ने और झूठे वापस आ जाओ। उन लोगों के लिए जो अन्यथा कहते हैं, यदि आप कार्यान्वयन को देखते हैं, तो यह पहले से ही एक मानचित्र का उपयोग करता है, और जेडीके डेवलपर्स के पास इसे अनुकूलित करने के लिए बहुत बेहतर मौका है। एपीआई एक अपवाद फेंकता है, जो एक बहस योग्य अभ्यास है (अशक्त लौटने के बजाय), लेकिन जब आप एक एपीआई के साथ सौदा करते हैं जो एक अपवाद को फेंकता है, तो इसके साथ जाओ, पहिया को सुदृढ़ न करें।
यिशै

2
@ ज्लुज़विक कोशिश / कैच ओवरहेड एक सरल कूद निर्देश है जब नहीं लिया जाता है, कैच ब्लॉक में अपवाद का उपयोग नहीं किया जाता है। प्रदर्शन के नुकसान की कोशिश / पकड़ के डर से एक बुरा अभ्यास है।
Best33s

22
इसमें () एक अपवाद के साथ valueOf () पर पसंद किया जाना है। क्यों? क्योंकि "अपवाद हैं, जैसा कि उनके नाम का तात्पर्य है, केवल असाधारण स्थितियों के लिए उपयोग किया जाना है; उन्हें कभी भी सामान्य नियंत्रण प्रवाह के लिए उपयोग नहीं किया जाना चाहिए" (जोशुआ बलोच, "प्रभावी जावा")।
james.garriss

226

इसके बजाय Apache commons lang3 lib का उपयोग करें

 EnumUtils.isValidEnum(MyEnum.class, myValue)

33
रुचि रखने वालों के लिए ध्यान दें, उनके द्वारा उपयोग किए जाने वाले अंतर्निहित कार्यान्वयन केवल कोशिश / पकड़ समाधान (@since 3.0 @version $ Id: EnumUtils.java 1199894 2011-11-09 17: 53: 59Z ggregory $) है।
जोनाथन गाव्रिएच 21

1
मेरे कोड को सरल बनाता है, इसलिए मुझे परवाह नहीं है अगर यह प्रवाह नियंत्रण के लिए अपवाद का उपयोग करता है (वे वास्तव में नहीं होना चाहिए ... यह अच्छा होगा यदि वे बदल गए।
२०:३१ पर jpangamarca


1
क्या अमरूद में भी इस तरह का घोल होता है?
सरू फ्रेंकेनफेल्ड

50

आप उपयोग कर सकते हैं Enum.valueOf()

enum Choices{A1, A2, B1, B2};

public class MainClass {
  public static void main(String args[]) {
    Choices day;

    try {
       day = Choices.valueOf("A1");
       //yes
    } catch (IllegalArgumentException ex) {  
        //nope
  }
}

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


8
मुझे नहीं लगता कि ऐसे मामले में अपवाद सबसे अच्छा विकल्प है।
गोकसेन

6
कोशिश और कैच अंतिम उपाय होना चाहिए। ट्राई एंड कैच काफी महंगा है
जीसस डाइमेक्स

2
व्यापार तर्क करने के लिए रनटाइम अपवादों में भरोसा करना, महंगा के अलावा, उतना पठनीय नहीं है। चेक किए गए अपवादों के बारे में, यह अलग है, क्योंकि वे व्यवसाय का हिस्सा बनाते हैं।
लुइस सोरेस

2
यह किसी को भी वास्तविक असाधारण मामलों को खोजने के लिए फेंके जा रहे अपवादों पर व्यापक विराम लगाने से रोकता है। (या कम से कम ऐसा करने पर बहुत गुस्सा आता है)। असाधारण मामलों के लिए अपवादों का उपयोग करें।
निकोलय कोंद्रतयेव

4
EnumUtils.isValidEnum(MyEnum.class, myValue)एक समान तर्क और IMO का उपयोग करता है जो इस तुच्छ कार्य के लिए पूरे पुस्तकालय को जोड़ने के लिए समझ में आता है
विक्रमजीत रॉय

37

यदि आप जावा 1.8 का उपयोग कर रहे हैं, तो आप इसे लागू करने के लिए स्ट्रीम + लैम्ब्डा चुन सकते हैं:

public enum Period {
    DAILY, WEEKLY
};

//This is recommended
Arrays.stream(Period.values()).anyMatch((t) -> t.name().equals("DAILY1"));
//May throw java.lang.IllegalArgumentException
Arrays.stream(Period.values()).anyMatch(Period.valueOf("DAILY")::equals);


19

ग्वावस एनम आपके मित्र हो सकते हैं

इस तरह से:

enum MyData {
    ONE,
    TWO
}

@Test
public void test() {

    if (!Enums.getIfPresent(MyData.class, "THREE").isPresent()) {
        System.out.println("THREE is not here");
    }
}

11

आप पहले enum को List में बदल सकते हैं और फिर सूची में विधि का उपयोग कर सकते हैं

enum Choices{A1, A2, B1, B2};

List choices = Arrays.asList(Choices.values());

//compare with enum value 
if(choices.contains(Choices.A1)){
   //do something
}

//compare with String value
if(choices.contains(Choices.valueOf("A1"))){
   //do something
}

यह स्वीकृत उत्तर होना चाहिए। सूची में रूपांतरण इसे करने का सबसे साफ तरीका है। यह जावा में "अपवादों के उचित उपयोग" के बारे में पूरी (पक्ष) चर्चा को अन्य उत्तरों में यहाँ पर बख्शता है।
मैनुअल

यदि मान मौजूद नहीं है, तो IllegalArgumentException को फेंक दें।
मिकॉन्ग

10

एक युगल पुस्तकालयों का उल्लेख यहां किया गया है, लेकिन मुझे वह याद आती है जिसे मैं वास्तव में ढूंढ रहा था: वसंत!

इसमें ObjectUtils # सम्‍मिलित सम्‍मिलित है जो डिफ़ॉल्ट रूप से असंवेदनशील है, लेकिन यदि आप चाहते हैं तो यह सख्त हो सकता है। इसका उपयोग इस तरह किया जाता है:

if(ObjectUtils.containsConstant(Choices.values(), "SOME_CHOISE", true)){
// do stuff
}

नोट: मैंने अति संवेदनशील विधि का उपयोग किया कि कैसे मामले की संवेदनशील जाँच का उपयोग किया जाए। आप असंवेदनशील व्यवहार के लिए बूलियन को छोड़ सकते हैं।

हालांकि वे कुछ के रूप में नक्शा कार्यान्वयन का उपयोग नहीं करते हैं, हालांकि बड़े enums के साथ सावधान रहें ...

एक बोनस के रूप में, यह मान के एक असंवेदनशील संस्करण भी प्रदान करता है: ObjectUtils # caseInsensitiveValueOf


9

कुछ धारणाएँ:
1) कोई कोशिश / पकड़ नहीं है, क्योंकि यह असाधारण प्रवाह नियंत्रण है
2) 'में' विधि त्वरित होनी चाहिए, क्योंकि यह आमतौर पर कई बार चलती है।
3) अंतरिक्ष सीमित नहीं है (सामान्य समाधानों के लिए सामान्य)

import java.util.HashSet;
import java.util.Set;

enum Choices {
    a1, a2, b1, b2;

    private static Set<String> _values = new HashSet<>();

    // O(n) - runs once
    static{
        for (Choices choice : Choices.values()) {
            _values.add(choice.name());
        }
    }

    // O(1) - runs several times
    public static boolean contains(String value){
        return _values.contains(value);
    }
}

7

आप इसका उपयोग कर सकते हैं

YourEnum {A1, A2, B1, B2}

boolean contains(String str){ 
    return Sets.newHashSet(YourEnum.values()).contains(str);
}                                  

@ Wightwulf1944 द्वारा सुझाए गए अपडेट को समाधान को अधिक कुशल बनाने के लिए शामिल किया गया है।


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

3

मुझे नहीं लगता कि वहाँ है, लेकिन आप ऐसा कुछ कर सकते हैं:

enum choices {a1, a2, b1, b2};

public static boolean exists(choices choice) {
   for(choice aChoice : choices.values()) {
      if(aChoice == choice) {
         return true;
      }
   }
   return false;
}

संपादित करें:

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


लेकिन मुझे लगता है कि ओपी एक स्ट्रिंग का परीक्षण करना चाहता है?
रिचर्ड एच

हां हा हा। यह तरीका उतना प्रभावी नहीं होगा जितना कि हम पहले से ही जानते हैं कि चुनाव एनम में है। आपका संशोधन अधिक सही है।
jluzwick

1
यदि आप Enums के कुछ सबसेट पर स्वयं काम करना चाहते हैं (और उनके नाम नहीं), तो EnumSet को देखने के लिए बेहतर है। download.oracle.com/javase/6/docs/api/java/util/EnumSet.html
Yishai

शायद एक बेवकूफी भरा सवाल है, लेकिन download.oracle.com/javase/6/docs/api/java/lang/Enum.html.values() पर प्रलेखित क्यों नहीं किया गया है ?
अनाम

यह बहुत अच्छा सवाल है। आप सही हैं कि यह दस्तावेज़ में मौजूद नहीं है और यह Enum स्रोत में भी मौजूद नहीं है। मैं मान रहा हूं कि यह Enum के कार्यान्वयन में से एक में मौजूद है या कुछ JLS नियम है जो इसके लिए अनुमति देता है। इसके अलावा सभी संग्रह वस्तुओं में यह है, और इसे एक संग्रह के रूप में देखा जा सकता है, भले ही यह आवश्यक रूप से संग्रह को लागू नहीं कर रहा हो।
1939 को jluzwick

3

जावा स्ट्रीम ऐसा करने के लिए सुरुचिपूर्ण तरीका प्रदान करती है

Stream.of(MyEnum.values()).anyMatch(v -> v.name().equals(strValue))

रिटर्न: सही है यदि स्ट्रीम का कोई भी तत्व प्रदान किए गए मूल्य से मेल खाता है, अन्यथा गलत है


2

पाब्लो के उत्तर को एक वैल्यूओफ़ () के साथ क्यों नहीं जोड़ा गया?

public enum Choices
{
    a1, a2, b1, b2;

    public static boolean contains(String s) {
        try {
            Choices.valueOf(s);
            return true;
        } catch (Exception e) {
            return false;
        }
}

कृपया नहीं। अन्य, पुराने उत्तर देखें जो आपके बराबर है: stackoverflow.com/a/4936872/103412
टॉरस्टेन

1

इस दृष्टिकोण का उपयोग किसी भी जाँच के लिए किया जा सकता है Enum, आप इसे एक Utilsवर्ग में जोड़ सकते हैं :

public static <T extends Enum<T>> boolean enumContains(Class<T> enumerator, String value)
{
    for (T c : enumerator.getEnumConstants()) {
        if (c.name().equals(value)) {
            return true;
        }
    }
    return false;
}

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

boolean isContained = Utils.enumContains(choices.class, "value");

1

मैंने इस सत्यापन के लिए अगली कक्षा बनाई

public class EnumUtils {

    public static boolean isPresent(Enum enumArray[], String name) {
        for (Enum element: enumArray ) {
            if(element.toString().equals(name))
                return true;
        }
        return false;
    }

}

उपयोग का उदाहरण:

public ArrivalEnum findArrivalEnum(String name) {

    if (!EnumUtils.isPresent(ArrivalEnum.values(), name))
        throw new EnumConstantNotPresentException(ArrivalEnum.class,"Arrival value must be 'FROM_AIRPORT' or 'TO_AIRPORT' ");

    return ArrivalEnum.valueOf(name);
}

0

valueOf("a1")यदि आप स्ट्रिंग द्वारा देखना चाहते हैं तो आप इसका उपयोग कर सकते हैं


3
लेकिन यह सुरुचिपूर्ण नहीं है .. यदि मूल्य मौजूद नहीं है तो यह एक अपवाद को फेंकता है। तो आप शायद इसे पकड़ने की कोशिश के साथ घेर लें
कस्तूरी

यदि मान मौजूद नहीं है तो अपवाद छोड़ देंगे
रिचर्ड एच।

एक मिलान वस्तु की तलाश में एनम विकल्पों के माध्यम से पुनरावृति की तुलना में कम सुरुचिपूर्ण?
jprete

0

यह एक एनम है, वे निरंतर मान हैं इसलिए यदि स्विच स्टेटमेंट में इसका ऐसा कुछ कर रहा है:

case: val1
case: val2

इसके अलावा आपको यह जानने की आवश्यकता क्यों होगी कि एक स्थिरांक के रूप में क्या घोषित किया गया है?


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

@ जो कि अब और अधिक समझ में आता है
Woot4Moo

@Jared हालांकि वास्तव में कोई फर्क नहीं पड़ता क्योंकि आप पहले से ही उन मूल्यों को जानते हैं जो वहां हैं। मूल रूप से list.contains () MyEnum.MyAwesomeValue
Woot4Moo

0

अमरूद के साथ यह और भी सरल है:

boolean isPartOfMyEnum(String myString){

return Lists.newArrayList(MyEnum.values().toString()).contains(myString);

}

जैसा कि कियोरिया ने कहा कि यह काम नहीं करेगा। MyEnum.values()MyEnum उदाहरणों की सरणी देता है और MyEnum.value().toString()इस सरणी ऑब्जेक्ट का स्ट्रिंग प्रतिनिधित्व देता है (बस स्ट्रिंग की तरह "[LMyEnum; @ 15b94ed3")
user2137020

आपको .name()इसके बजाय कॉल करने की आवश्यकता है .toString()(जब तक कि आप डिफ़ॉल्टString विधि को ओवरराइड नहीं करते)। अधिक जानकारी के लिए इसे देखें: enum .name () और .toString ()
Gaʀʀʏ के

0

यह पिछले तरीकों से सभी दृष्टिकोणों को जोड़ती है और समान प्रदर्शन होना चाहिए। इसका उपयोग किसी भी एनम के लिए किया जा सकता है, @Richard H से "एडिट" सॉल्यूशन को इनलाइन करता है और @bestsss जैसे अमान्य मानों के लिए अपवाद का उपयोग करता है। एकमात्र व्यापार यह है कि वर्ग को निर्दिष्ट करने की आवश्यकता है, लेकिन यह इसे दो-लाइनर में बदल देता है।

import java.util.EnumSet;

public class HelloWorld {

static enum Choices {a1, a2, b1, b2}

public static <E extends Enum<E>> boolean contains(Class<E> _enumClass, String value) {
    try {
        return EnumSet.allOf(_enumClass).contains(Enum.valueOf(_enumClass, value));    
    } catch (Exception e) {
        return false; 
    }
}

public static void main(String[] args) {
    for (String value : new String[] {"a1", "a3", null}) {
        System.out.println(contains(Choices.class, value));
    }
}

}



0

यह जाँचने के लिए कि क्या मूल्य मौजूद है और बदले में एनम मूल्य प्राप्त करें:

protected TradeType getEnumType(String tradeType) {
    if (tradeType != null) {
        if (EnumUtils.isValidEnum(TradeType.class, tradeType)) {
            return TradeType.valueOf(tradeType);
        }
    }
    return null;
}

0

यह एक मेरे लिए काम करता है:

Arrays.asList(YourEnum.values()).toString().contains("valueToCheck");

3
आपका संस्करण तब भी सच हो जाएगा जब YourEnum में "valueToCheckBlaBla" होगा, क्योंकि "valueToCheck" पूरी सूची के स्ट्रिंग प्रतिनिधित्व में मौजूद होगा।
निको

0

यदि आप जावा 8 या इसके बाद के संस्करण का उपयोग कर रहे हैं, तो आप यह कर सकते हैं:

boolean isPresent(String testString){
      return Stream.of(Choices.values()).map(Enum::name).collect(Collectors.toSet()).contains(testString);
}


0

आप इसे विधि के रूप में बना सकते हैं:

enum choices {a1, a2, b1, b2};
public boolean contains(String value){
    try{
        EnumSet.allOf(choices.class).contains(Enum.valueOf(choices.class, value));
        return true;
    }catch (Exception e) {
        return false;
    }
}

या आप इसे अपने कोड ब्लॉक के साथ उपयोग कर सकते हैं:

try{
    EnumSet.allOf(choices.class).contains(Enum.valueOf(choices.class, "a1"));
    //do something
}catch (Exception e) {
    //do something else
}

0

आप यह भी उपयोग कर सकते हैं: com.google.common.base.Enums

Enums.getIfPresent (varEnum.class, varToLookFor) एक वैकल्पिक रिटर्न देता है

Enums.getIfPresent (fooEnum.class, myVariable) .isPresent ()? Enums.getIfPresent (fooEnum.class, myVariable) .get: fooEnum.OTHERS


0

मैं बस लिखूंगा,

Arrays.stream(Choice.values()).map(Enum::name).collect(Collectors.toList()).contains("a1");

एनम # बराबर केवल ऑब्जेक्ट तुलना के साथ काम करता है।


-1
public boolean contains(Choices value) {
   return EnumSet.allOf(Choices.class).contains(value);
}

वह काम नहीं करेगा। सेट में एनम ऑब्जेक्ट्स हैं, जबकि आपका स्ट्रिंग के लिए जाँच कर रहा है।
iTake

अब जवाब सवाल फिट नहीं है, क्योंकि यह स्ट्रिंग के बारे में था :)
iTake

-11

enumजावा में बहुत शक्तिशाली हैं। आप आसानी containsसे अपने एनम में एक विधि जोड़ सकते हैं (जैसा कि आप एक वर्ग में एक विधि जोड़ सकते हैं):

enum choices {
  a1, a2, b1, b2;

  public boolean contains(String s)
  {
      if (s.equals("a1") || s.equals("a2") || s.equals("b1") || s.equals("b2")) 
         return true;
      return false;
  } 

};

क्या आपका मतलब था s.equals("b1") || s.equals("b2")??
जिगर जोशी

3
यह शायद ऐसा करने का सबसे अच्छा तरीका नहीं होगा क्योंकि आपको s.equals("xx")बाद में जोड़ने वाले प्रत्येक एनम के लिए नया जोड़ना होगा ।
jluzwick

1
और वहाँ एक 1000 + enums होने जा रहा है।
जारेड

20
जो लोग इस तरह के भयानक समाधान सुझाते हैं, उन्हें 64K प्रतिष्ठा कैसे मिलती है? मैं सभी भद्दे कोड के बारे में सोचने से नफरत करता हूं, जो इस योगदानकर्ताओं के जवाबों के आधार पर बाहर हो जाते हैं
डेक्सिजन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.