2012-06-15 21 views
63

पहले पूर्णांक मूल्य के साथ जुड़े enum, मैं अपने Legno enums के रूप में बस में परिभाषित किया गया था:हो रही

NO_LEG, LEG_ONE, LEG_TWO 

और return LegNo.values()[i]; फोन करके, मैं प्रत्येक enum के साथ जुड़े मूल्य प्राप्त करने में सक्षम था।

लेकिन अब मैं तय कर लिया है मैं LegNo enum NO_LEG चाहते पूर्णांक होना करने के लिए -1 की बजाय 0 तो मैं आरंभ करने के लिए एक निजी निर्माता का उपयोग करने का फैसला किया और इसके पूर्णांक मान सेट

NO_LEG(-1), LEG_ONE(1), LEG_TWO(2); 

private LegNo(final int leg) { legNo = leg; } 

केवल अब बात यह है कि क्योंकि मैं इसे values() विधि NO_LEG enum के लिए काम नहीं करूँगा। मैं int से जुड़े enum कैसे प्राप्त करूं? वहाँ अगर-elseif-elseif एक मामले स्विच बयान या एक का उपयोग करने से यह अन्य कर के किसी भी कारगर तरीका है

मैं इतना सवाल enum से पूर्णांक मान प्राप्त कर रहा से कोई लेना देना का एक बहुत देख सकते हैं, लेकिन यह है कि मैं कर रहा हूँ रिवर्स के बाद।

उत्तर

115

आपको enum के अंदर मैपिंग बनाए रखना होगा।

public enum LegNo { 
    NO_LEG(-1), LEG_ONE(1), LEG_TWO(2); 

    private int legNo; 

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

    static { 
     for (LegNo legEnum : LegNo.values()) { 
      map.put(legEnum.legNo, legEnum); 
     } 
    } 

    private LegNo(final int leg) { legNo = leg; } 

    public static LegNo valueOf(int legNo) { 
     return map.get(legNo); 
    } 
} 

स्थैतिक ब्लॉक केवल एक बार लागू किया जाएगा, इसलिए व्यावहारिक रूप से यहां कोई प्रदर्शन समस्या नहीं है।

संपादित करें: valueOf पर विधि का नाम बदलें क्योंकि यह अन्य जावा कक्षाओं के साथ अधिक इनलाइन है।

+0

खेद im। मैं int में गुजरना चाहता हूं और इसके साथ जुड़े enum प्राप्त करना चाहता हूँ। –

+0

@ एल-सैमुअल्स मान लीजिए मैंने आपके प्रश्न को ठीक से नहीं पढ़ा है। मेरा अपडेट देखें। – adarshr

+1

मुझे पता है कि यह स्पष्ट प्रतीत होता है, लेकिन इसका उपयोग इस तरह करें: 'LegNo foo = LegNo.valueOf (2); '। पिछला कोड 'LegNo.LEG_TWO' वापस करेगा। – FirstOne

1

चूंकि आपके enum में केवल 3 तत्व होते हैं, इसलिए सबसे तेज़ तरीका केवल if else की श्रृंखला का उपयोग करना होगा, जैसा आपने सुझाव दिया था।

संपादित करें: प्रदान किया गया उत्तर सामान्य मामलों के लिए बेहतर है, जहां कई enum मान हैं, लेकिन मुझे लगता है कि यह आपकी समस्या के लिए एक अधिक है।

+0

आपके कोड में 'मानचित्र' रखना निश्चित रूप से एक overkill नहीं। इसके अलावा यह विधि किसी अन्य स्थिति की स्पेगेटी की तुलना में बहुत साफ है। – adarshr

+0

मैं मानता हूं कि आपके पास बहुत सारे मूल्यवान मूल्य होने के बाद मानचित्र बेहतर होता है, लेकिन 3 मानों के लिए मैं एक/अन्य निर्माण के लिए चिपक जाता हूं। यह मुझे लगता है स्वाद का मामला है। – DieterDP

+0

जो भी दृष्टिकोण हम चुनते हैं, 'सार्वजनिक LegNo valueOf (int मान)' के विधि हस्ताक्षर को बदला नहीं जाना चाहिए। अगर और फिर enum के भीतर लिखा जा सकता है। अगर अगर एनम से बाहर निकलता है, तो यह निश्चित रूप से एक साफ-सुथरा कोड बन जाता है। – adarshr

-4
public enum body 
{ 
    NO_LEG = 0,   // bit 1 
    LEG_ONE = 2,  // bit 2 
    LEG_TWO = 4,  // bit 3 
    NO_ARM = 8,   // bit 4 
    ARM_ONE = 16, // bit 5 
    ARM_TWO = 32 // bit 6 

} 

इसे (int) body.LEG_ONE; /// जो 2

देता है यह संकलन समय पर किया जाता है क्योंकि यह भी बहुत तेज़ और आसान पठनीय है।

+7

यह जावा एनम्स के लिए मान्य नहीं है। –

17

आप enum में एक स्थैतिक विधि भी शामिल कर सकते हैं जो सभी सदस्यों के माध्यम से पुनरावृत्ति करता है और सही एक देता है।

public enum LegNo { 
    NO_LEG(-1), 
    LEG_ONE(1), 
    LEG_TWO(2); 

    private int legIndex; 

    private LegNo(int legIndex) { this.legIndex = legIndex; } 

    public static LegNo getLeg(int legIndex) { 
     for (LegNo l : LegNo.values()) { 
      if (l.legIndex == legIndex) return l; 
     } 
     throw new IllegalArgumentException("Leg not found. Amputated?"); 
    } 
} 

अब, आप पूर्णांक द्वारा एक Enum लाभ प्राप्त करना चाहते हैं, तो आप सिर्फ का उपयोग करें:

int myLegIndex = 1; //expected : LEG_ONE 
LegNo myLeg = LegNo.getLeg(myLegIndex); 
+0

मुझे लगता है कि अगर यह कथन है तो इसका उपयोग करने से अधिक सुरुचिपूर्ण होगा। लेकिन वहां पर अधिक प्रचलित खोज के बाद @adarshr द्वारा सुझाए गए मानचित्र रणनीति बेहतर होगी। हालांकि हास्य के लिए वोट दें। –

+1

मुझे नक्शा रणनीति बहुत पसंद है। विशेष रूप से जब enum या तो बहुत सारे मूल्य हैं या इसे अक्सर इस तंत्र के माध्यम से देखा जाना चाहिए। हालांकि, यदि संबंधित int द्वारा मानों को देखना एक अपेक्षाकृत दुर्लभ घटना है या आपके पास एक ही लुकअप आवश्यकता के साथ कई अलग-अलग enums हैं, तो मेरा मानना ​​है कि मेरा तरीका अधिक संसाधन अनुकूल होगा, क्योंकि मानचित्र के लिए ओवरहेड सहेजा गया है। इसके अलावा, मुझे लगता है कि यह कम अव्यवस्थित कोड के लिए बनाता है। मेरे पास कुछ उपयोग-मामले हैं जहां मैं निश्चित रूप से मानचित्र-प्रकार पर स्विच करूँगा, हालांकि। –

+0

आपको अपने ordinal द्वारा कभी भी संबद्ध एनम मान प्राप्त नहीं करना चाहिए। एक स्थिर मानचित्र का उपयोग जावा आर्किटेक्ट्स द्वारा अनुशंसित पद्धति है। – hfontanez

0
public enum LegNo { 
    NO_LEG(-1), LEG_ONE(1), LEG_TWO(2); 

    private int legNo; 

    private LegNo(int leg) { legNo = leg; } 

    public static LegNo valueOf(int legNo) { 
     for (LegNo leg : LegNo.values()) { 
      if (leg.legNo == legNo) return leg; 
     } 
    } 
} 

assert LegNo.valueOf(2) == LegNo.LEG_TWO 
assert LegNo.valueOf(3) == null 
+4

<10 मानों के साथ enums के लिए स्वीकार्य लेकिन लुकअप जटिलता ओ (एन) की वजह से बड़ी संख्या में enum मूल्यों के लिए पूरी तरह से अप्रभावी – Alfishe

10

adarshr's answer जावा 8 के लिए अनुकूलित:

import static java.util.Arrays.stream; 
import static java.util.stream.Collectors.toMap; 

import java.util.Map; 

public enum LegNo { 
    NO_LEG(-1), LEG_ONE(1), LEG_TWO(2); 

    private final int legNo; 

    private final static Map<Integer, LegNo> map = 
      stream(LegNo.values()).collect(toMap(leg -> leg.legNo, leg -> leg)); 

    private LegNo(final int leg) { 
     legNo = leg; 
    } 

    public static LegNo valueOf(int legNo) { 
     return map.get(legNo); 
    } 
} 
4

आप कर सकते हैं enum LegNo पर मूल्यों() विधि को कॉल करके दिए गए पूर्णांक मान से संबंधित एनम मान भी एक्सेस करें। यह लेगनो एनम्स का क्षेत्र लौटाता है: LegNo.values[0]; //returns LEG_NO LegNo.values[1]; //returns LEG_ONE LegNo.values[2]; //returns LEG_TWO

ठीक वही चीज़ जो वह ढूंढ रही थी, लेकिन वास्तव में बहुत करीब और बहुत सरल है। (हालांकि विषय मर चुका है यह किसी और के लिए उपयोगी हो सकता है।) डिफ़ॉल्ट मान के साथ

3

जावा 8 रास्ता:

public enum LegNo { 
    NO_LEG(-1), LEG_ONE(1), LEG_TWO(2); 

    private final int legNo; 

    LegNo(int legNo) { 
     this.legNo = legNo; 
    } 

    public static LegNo find(int legNo, Supplier<? extends LegNo> byDef) { 
     return Arrays.asList(LegNo.values()).stream() 
       .filter(e -> e.legNo == legNo).findFirst().orElseGet(byDef); 
    } 
} 

कॉल करने के लिए:

LegNo res = LegNo.find(0,() -> LegNo.NO_LEG); 

या अपवाद के साथ: यकीन है कि अगर मैं पर्याप्त स्पष्ट था नहीं

LegNo res = LegNo.find(0,() -> { 
    throw new RuntimeException("No found"); 
});