Enum और int / String के बीच आसानी से नक्शा


108

जब वे चर / मापदंडों के साथ काम कर रहे हैं जो केवल एक सीमित संख्या में मान ले सकते हैं, तो मैं हमेशा जावा के उपयोग की कोशिश करता हूं enum, जैसे कि

public enum BonusType {
  MONTHLY, YEARLY, ONE_OFF
}

जब तक मैं अपने कोड के अंदर रहता हूं, वह ठीक काम करता है। हालांकि, मुझे अक्सर अन्य कोड के साथ इंटरफ़ेस करने की आवश्यकता होती है जो सादे int(या) का उपयोग करता हैString जो समान उद्देश्य के लिए ) मूल्यों करते हैं, या मुझे एक डेटाबेस से पढ़ने / लिखने की आवश्यकता होती है जहां डेटा को एक संख्या या स्ट्रिंग के रूप में संग्रहीत किया जाता है।

उस स्थिति में, मैं एक एनम मूल्य को पूर्णांक के साथ जोड़ने के लिए एक सुविधाजनक तरीका चाहता हूं, जैसे कि मैं दोनों तरीकों को बदल सकता हूं (दूसरे शब्दों में, मुझे "प्रतिवर्ती एनम" की आवश्यकता है)।

एनम से इंट में जाना आसान है:

public enum BonusType {
  public final int id;

  BonusType(int id) {
    this.id = id;
  }
  MONTHLY(1), YEARLY(2), ONE_OFF(3);
}

तब मैं int मान को एक्सेस कर सकता हूं BonusType x = MONTHLY; int id = x.id;

हालाँकि, मैं रिवर्स के लिए कोई अच्छा तरीका नहीं देख सकता, यानी इंटम से एनुम तक जा रहा हूं। आदर्श रूप में, कुछ पसंद है

BonusType bt = BonusType.getById(2); 

एकमात्र समाधान जो मैं ले सकता था, वे हैं:

  • Enum में एक लुकअप विधि रखो, जो उपयोग करता है BonusType.values() मैप "int -> enum" को भरने के लिए है, फिर कैश करता है और लुकअप के लिए इसका उपयोग करता है। काम करेगा, लेकिन मुझे इस विधि की पहचान प्रत्येक enum में कॉपी करनी होगी जिसका मैं उपयोग करता हूं :-(
  • लुकअप विधि को एक स्थिर उपयोगिता वर्ग में रखें। तब मुझे केवल एक "लुकअप" विधि की आवश्यकता होगी, लेकिन मुझे मनमाने ढंग से एनम के लिए काम करने के लिए प्रतिबिंब के साथ फील करना होगा।

इस तरह की एक सरल (?) समस्या के लिए दोनों तरीके बहुत अजीब लगते हैं।

कोई अन्य विचार / अंतर्दृष्टि?


1
मैं <3 जावा enums लेकिन उन्हें इस कारण से बिल्कुल नफरत करता हूं! यह हमेशा ऐसा लगता है जैसे वे वास्तव में एक बदसूरत दोष से अलग हैं ...
क्रिस थॉम्पसन

8
enum-> int के लिए आप बस इस्तेमाल कर सकते हैंordinal()
davin

1
क्या आपके आईडी-वैल्यू आपके द्वारा निर्णायक हैं (मतलब, आप सिर्फ इस्तेमाल नहीं कर सकते थे .ordinal()), या क्या वे बाहरी ताकतों द्वारा तय किए गए हैं?
पाओलो एबरमन

2
@davin: हाँ, और आपका कोड उस पल को तोड़ देता है जब कोई व्यक्ति एनम घोषणा को पुन: व्यवस्थित करता है, या बीच में एक मान हटा देता है। मुझे डर है कि यह एक मजबूत समाधान नहीं है: - /।
19

1
"ऑर्डिनल ()" का उपयोग करते हुए @davin को जब भी संभव हो बचना चाहिए, यह भाषा के विनिर्देश में है
DPM

जवाबों:


37

http://www.javaspecialists.co.za/archive/Issue113.html

एनुम परिभाषा के हिस्से के रूप में एक अंतर मूल्य के साथ समाधान आपके समान शुरू होता है। फिर वह जेनरिक-आधारित लुकअप उपयोगिता बनाने के लिए आगे बढ़ता है:

public class ReverseEnumMap<V extends Enum<V> & EnumConverter> {
    private Map<Byte, V> map = new HashMap<Byte, V>();
    public ReverseEnumMap(Class<V> valueType) {
        for (V v : valueType.getEnumConstants()) {
            map.put(v.convert(), v);
        }
    }

    public V get(byte num) {
        return map.get(num);
    }
}

यह समाधान अच्छा है और इसके लिए 'फ़िडलिंग विथ परावर्तन' की आवश्यकता नहीं है क्योंकि यह इस तथ्य पर आधारित है कि सभी एनम प्रकारों में निहित एनम इंटरफ़ेस होता है।


क्या यह अध्यादेश का उपयोग नहीं करता है? Sleske एक आईडी का उपयोग सिर्फ इसलिए करता है कि जब आयम मान पुनः व्यवस्थित हो जाते हैं, तो क्रमिक परिवर्तन होते हैं।
extraneon

नहीं, यह अध्यादेश का उपयोग नहीं करता है। यह स्पष्ट रूप से परिभाषित इंट वैल्यू पर निर्भर करता है। उस इंट वैल्यू का इस्तेमाल मैप की (v.convert () द्वारा लौटाया गया) के रूप में किया जाता है।
जेफ

2
मुझे वास्तव में यह समाधान पसंद है; ऐसा लगता है कि यह सबसे सामान्य है जिसे आप प्राप्त कर सकते हैं।
sleske

+1। मेरा एकमात्र नोट यह है कि मैं Numberइसके बजाय उपयोग Byteकरूंगा, क्योंकि मेरा समर्थन मूल्य आकार में बड़ा हो सकता है।
Ivaylo Slavov

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

327

एनम → इंट

yourEnum.ordinal()

int → एनुम

EnumType.values()[someInt]

स्ट्रिंग → एनुम

EnumType.valueOf(yourString)

एनम → स्ट्रिंग

yourEnum.name()

एक साइड-नोट:
जैसा कि आप सही ढंग से बताते हैं, ordinal()संस्करण से संस्करण तक "अस्थिर" हो सकता है। यह सटीक कारण है कि मैं हमेशा अपने डेटाबेस में तार के रूप में स्थिरांक जमा करता हूं। (वास्तव में, MySql का उपयोग करते समय, मैं उन्हें MySql enums के रूप में संग्रहीत करता हूं !)


2
+1 यह स्पष्ट सही उत्तर है। ध्यान दें, मान के लिए एक एकल तर्क विधि है जो केवल एक स्ट्रिंग लेता है और जब तक आप ठोस एनुम प्रकार (जैसे BonusType.valueOf("MONTHLY")) का उपयोग कर रहे हैं तब तक मौजूद रहता है
टिम बेंडर

18
ordinal()स्ट्राइक सॉल्यूशन के रूप में स्ट्राइक का इस्तेमाल करना , क्योंकि जब एनम वैल्यूज़ की लिस्ट फिर से आ जाएगी या वैल्यू डिलीट हो जाती है तो वह टूट जाएगा। इसके अलावा, यह केवल तभी व्यावहारिक होता है जब इंट वैल्यू 0 हो ... n (जो मैंने अक्सर पाया है कि मामला नहीं है)।
20

4
यदि आप लगातार किसी भी तरह के मौजूदा डेटा को लेकर परेशान हैं, तो @sleske, यदि आप लगातार हटाना शुरू कर देते हैं। (इस संबंध में मेरा जवाब अपडेट करें।)
aioobe

3
values()सरणी का उपयोग केवल तभी काम करेगा जब आपके सभी मान उनकी आईडी के लिए अनुक्रमित हों और क्रम में घोषित किए गए हों। (मैंने इसे सत्यापित करने के लिए परीक्षण किया कि यदि आप घोषणा करते हैं FOO(0), BAR(2), BAZ(1);कि values[1] == BARऔर values[2] == BAZआईडी पास होने के बावजूद।)
corsiKa

2
@glowcoder, अच्छी तरह से, पूर्णांक तर्क केवल एनम-ऑब्जेक्ट में एक फ़ील्ड है। इसका एनुम वस्तु से जुड़े क्रमिक स्थिरांक से कोई लेना-देना नहीं है (यह बस हो सकता है double)।
aioobe

29

मैंने इसे वेब पर पाया, यह लागू करने में बहुत मददगार और सरल था। यह समाधान मेरे द्वारा नहीं किया गया था

http://www.ajaxonomy.com/2007/java/making-the-most-of-java-50-enum-tricks

public enum Status {
 WAITING(0),
 READY(1),
 SKIPPED(-1),
 COMPLETED(5);

 private static final Map<Integer,Status> lookup 
      = new HashMap<Integer,Status>();

 static {
      for(Status s : EnumSet.allOf(Status.class))
           lookup.put(s.getCode(), s);
 }

 private int code;

 private Status(int code) {
      this.code = code;
 }

 public int getCode() { return code; }

 public static Status get(int code) { 
      return lookup.get(code); 
 }

}


s / EnumSet.allOf (Status.class) /Status.values ​​()
जेलिंसन

8

लगता है कि इस सवाल का जवाब (एस) जावा 8 की रिलीज के साथ पुराना है।

  1. यदि JVM जैसे डेटाबेस से बाहर कायम है, तो अध्यादेश का उपयोग न करें क्योंकि अध्यादेश अस्थिर है।
  2. मुख्य मूल्यों के साथ स्थैतिक मानचित्र बनाना अपेक्षाकृत आसान है।

public enum AccessLevel {
  PRIVATE("private", 0),
  PUBLIC("public", 1),
  DEFAULT("default", 2);

  AccessLevel(final String name, final int value) {
    this.name = name;
    this.value = value;
  }

  private final String name;
  private final int value;

  public String getName() {
    return name;
  }

  public int getValue() {
    return value;
  }

  static final Map<String, AccessLevel> names = Arrays.stream(AccessLevel.values())
      .collect(Collectors.toMap(AccessLevel::getName, Function.identity()));
  static final Map<Integer, AccessLevel> values = Arrays.stream(AccessLevel.values())
      .collect(Collectors.toMap(AccessLevel::getValue, Function.identity()));

  public static AccessLevel fromName(final String name) {
    return names.get(name);
  }

  public static AccessLevel fromValue(final int value) {
    return values.get(value);
  }
}

का दूसरा पैरामीटर नहीं करना चाहिए Collectors.toMap()होना Functions.identity()बजाय null?
एडम मिशालिक

हाँ, मैंने इसे एक ऐसे सहायक वर्ग से अपनाया है जिसका उपयोग मैं अमरूद के साथ करता हूँ जो अशक्त को पहचान में परिवर्तित करता है।
जॉन मेयर

यह जावा 8 की नई सुविधाओं का एक साफ उपयोग है। हालांकि, इसका मतलब यह है कि कोड को हर एनुम में दोहराया जाना होगा - और मेरा सवाल इस (संरचनात्मक रूप से) दोहराए जाने वाले बॉयलरप्लेट से बचने के बारे में था।
sleske

5

org.apache.commons.lang.enums.ValuedEnum;

मुझे प्रत्येक एनम के लिए बॉयलरप्लेट कोड या डुप्लिकेटिंग कोड का भार लिखने से बचाने के लिए, मैंने अपाचे कॉमन्स लैंग का उपयोग किया ValuedEnum बजाय ।

परिभाषा :

public class NRPEPacketType extends ValuedEnum {    
    public static final NRPEPacketType TYPE_QUERY = new NRPEPacketType( "TYPE_QUERY", 1);
    public static final NRPEPacketType TYPE_RESPONSE = new NRPEPacketType( "TYPE_RESPONSE", 2);

    protected NRPEPacketType(String name, int value) {
        super(name, value);
    }
}

उपयोग:

int -> मान्य

NRPEPacketType packetType = 
 (NRPEPacketType) EnumUtils.getEnum(NRPEPacketType.class, 1);

अच्छा विचार है, मुझे एहसास नहीं था कि यह अस्तित्व में है। साझा करने के लिए धन्यवाद!
कीथ पी

3

आप शायद कुछ का उपयोग कर सकते हैं

interface EnumWithId {
    public int getId();

}


enum Foo implements EnumWithId {

   ...
}

यह आपके उपयोगिता वर्ग में प्रतिबिंब की आवश्यकता को कम करेगा।


क्या आप इस स्निपेट का उपयोग करने का एक उदाहरण दे सकते हैं?
इगोरगानपोलस्की

3

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

public enum Test{ 
VALUE_ONE(101, "Im value one"),
VALUE_TWO(215, "Im value two");
private final int number;
private final byte[] desc;

private final static int[] converter = new int[216];
static{
    Test[] st = values();
    for(int i=0;i<st.length;i++){
        cv[st[i].number]=i;
    }
}

Test(int value, byte[] description) {
    this.number = value;
    this.desc = description;
}   
public int value() {
    return this.number;
}
public byte[] description(){
    return this.desc;
}

public static String description(int value) {
    return values()[converter[rps]].desc;
}

public static Test fromValue(int value){
return values()[converter[rps]];
}
}

2

इसे दिखाने के लिए एक इंटरफ़ेस का उपयोग करें जो बॉस का है।

public interface SleskeEnum {
    int id();

    SleskeEnum[] getValues();

}

public enum BonusType implements SleskeEnum {


  MONTHLY(1), YEARLY(2), ONE_OFF(3);

  public final int id;

  BonusType(int id) {
    this.id = id;
  }

  public SleskeEnum[] getValues() {
    return values();
  }

  public int id() { return id; }


}

public class Utils {

  public static SleskeEnum getById(SleskeEnum type, int id) {
      for(SleskeEnum t : type.getValues())
          if(t.id() == id) return t;
      throw new IllegalArgumentException("BonusType does not accept id " + id);
  }

  public static void main(String[] args) {

      BonusType shouldBeMonthly = (BonusType)getById(BonusType.MONTHLY,1);
      System.out.println(shouldBeMonthly == BonusType.MONTHLY);

      BonusType shouldBeMonthly2 = (BonusType)getById(BonusType.MONTHLY,1);
      System.out.println(shouldBeMonthly2 == BonusType.YEARLY);

      BonusType shouldBeYearly = (BonusType)getById(BonusType.MONTHLY,2);
      System.out.println(shouldBeYearly  == BonusType.YEARLY);

      BonusType shouldBeOneOff = (BonusType)getById(BonusType.MONTHLY,3);
      System.out.println(shouldBeOneOff == BonusType.ONE_OFF);

      BonusType shouldException = (BonusType)getById(BonusType.MONTHLY,4);
  }
}

और परिणाम:

C:\Documents and Settings\user\My Documents>java Utils
true
false
true
true
Exception in thread "main" java.lang.IllegalArgumentException: BonusType does not accept id 4
        at Utils.getById(Utils.java:6)
        at Utils.main(Utils.java:23)

C:\Documents and Settings\user\My Documents>

1
बस के रूप में Turd Ferguson के जवाब के साथ, यह है कि मैं से बचने के लिए / सुधार करना चाहते हैं
अभिमानी

मैं आमतौर पर एक स्थिर {} ब्लॉक में रिवर्स मैपिंग का निर्माण करता हूं, ताकि मुझे हर बार आईडी द्वारा मान पूछने के लिए मूल्यों () पर लूप न करना पड़े। मैं आम तौर पर विधि valueOf (int) को कॉल करता हूं, ताकि यह कुछ ऐसा प्रतीत हो जैसे कि ValueOf (स्ट्रिंग) विधि पहले से ही स्ट्रिंग्स (ओपी के प्रश्न का हिस्सा) के लिए भी है। प्रभावी जावा में आइटम 33 की तरह कुछ: smallurl.com/4ffvc38
फ्रेड्रिक

अधिक परिष्कृत समाधान के साथ @Sleske अपडेट किया गया। @ दिलचस्प, हालांकि मुझे संदेह है कि पुनरावृत्ति एक महत्वपूर्ण मुद्दा होने जा रहा है।
corsiKa

@glowcoder अच्छी तरह से, एक से अधिक बार पुनरावृत्त होने का मतलब यह नहीं है कि इससे कोई फर्क नहीं पड़ता कि आप इसे प्रति सेकंड एक हजार बार करते हैं जहां यह एक बहुत महत्वपूर्ण मुद्दा हो सकता है या बस इसे दो बार कॉल कर सकता है।
फ्रेड्रिक

@Fredrik मैं मानता हूँ कि ऐसे समय हैं जहाँ अनुकूलन करना आवश्यक हो सकता है। मैं यह भी कह रहा हूं कि जब तक यह एक पहचानी गई प्रदर्शन समस्या नहीं है, तब तक इसके लिए अनुकूलन न करें।
corsiKa

2

दोनों .ordinal()औरvalues()[i] अस्थिर क्योंकि वे enums के आदेश करने के लिए निर्भर कर रहे हैं कर रहे हैं। इस प्रकार यदि आप enums का क्रम बदलते हैं या कुछ जोड़ते / हटाते हैं तो आपका प्रोग्राम टूट जाएगा।

यहाँ enum और int के बीच मैप करने के लिए एक सरल लेकिन प्रभावी तरीका है।

public enum Action {
    ROTATE_RIGHT(0), ROTATE_LEFT(1), RIGHT(2), LEFT(3), UP(4), DOWN(5);

    public final int id;
    Action(int id) {
        this.id = id;
    }

    public static Action get(int id){
        for (Action a: Action.values()) {
            if (a.id == id)
                return a;
        }
        throw new IllegalArgumentException("Invalid id");
    }
}

तार के लिए इसे लागू करना मुश्किल नहीं होना चाहिए।


हां, मुझे लगता है कि मैं ऐसा कर सकता हूं - या इससे भी बेहतर, सभी मूल्यों के माध्यम से पुनरावृति के बजाय रिवर्स लुकअप के लिए एक मानचित्र का उपयोग करें। मैंने अपने प्रश्न में इसका उल्लेख किया है, और मैंने यह भी उल्लेख किया है कि मैं एक बेहतर समाधान की तलाश कर रहा हूं, ताकि प्रत्येक एनम में बॉयलरप्लेट कोड होने से बचा जा सके।
'10

2

रिवर्स एनम का एक बहुत साफ उपयोग उदाहरण

चरण 1 एक interfaceEnumConverter को परिभाषित करें

public interface EnumConverter <E extends Enum<E> & EnumConverter<E>> {
    public String convert();
    E convert(String pKey);
}

चरण 2

एक वर्ग नाम बनाएँ ReverseEnumMap

import java.util.HashMap;
import java.util.Map;

public class ReverseEnumMap<V extends Enum<V> & EnumConverter<V>> {
    private Map<String, V> map = new HashMap<String, V>();

    public ReverseEnumMap(Class<V> valueType) {
        for (V v : valueType.getEnumConstants()) {
            map.put(v.convert(), v);
        }
    }

    public V get(String pKey) {
        return map.get(pKey);
    }
}

चरण 3

आप के लिए Enumवर्ग जाओ और implementइसके साथ EnumConverter<ContentType>और अंत में इंटरफ़ेस विधियों को ओवरराइड करें। आपको एक स्थिर ReverseEnumMap को इनिशियलाइज़ करने की भी आवश्यकता है।

public enum ContentType implements EnumConverter<ContentType> {
    VIDEO("Video"), GAME("Game"), TEST("Test"), IMAGE("Image");

    private static ReverseEnumMap<ContentType> map = new ReverseEnumMap<ContentType>(ContentType.class);

    private final String mName;

    ContentType(String pName) {
        this.mName = pName;
    }

    String value() {
        return this.mName;
    }

    @Override
    public String convert() {
        return this.mName;
    }

    @Override
    public ContentType convert(String pKey) {
        return map.get(pKey);
    }
}

चरण 4

अब एक बनाने के Communicationवर्ग फ़ाइल और कॉल यह नया तरीका एक कन्वर्ट करने के लिए है Enumकरने के लिए Stringऔर Stringकरने के लिए Enum। मैंने स्पष्टीकरण उद्देश्य के लिए सिर्फ मुख्य विधि रखी है।

public class Communication<E extends Enum<E> & EnumConverter<E>> {
    private final E enumSample;

    public Communication(E enumSample) {
        this.enumSample = enumSample;
    }

    public String resolveEnumToStringValue(E e) {
        return e.convert();
    }

    public E resolveStringEnumConstant(String pName) {
        return enumSample.convert(pName);
    }

//Should not put main method here... just for explanation purpose. 
    public static void main(String... are) {
        Communication<ContentType> comm = new Communication<ContentType>(ContentType.GAME);
        comm.resolveEnumToStringValue(ContentType.GAME); //return Game
        comm.resolveStringEnumConstant("Game"); //return GAME (Enum)
    }
}

पूर्ण विवरण के लिए क्लिक करें


1
यह मैं वास्तव में, वास्तव में पसंद करता हूं - मैं पिछले कुछ समय से इस समस्या का ठोस समाधान खोज रहा हूं। मेरे द्वारा किया गया एकमात्र परिवर्तन ContentType convert(String pKey)स्थिर करना था , जो Communicationवर्ग की आवश्यकता को दूर करता है और मेरी पसंद के हिसाब से अधिक था। +1
क्रिस मेंटल

1

मुझे यकीन नहीं है कि यह जावा में समान है, लेकिन सी में एनम प्रकार स्वचालित रूप से पूर्णांकों के लिए मैप किए जाते हैं ताकि आप इसे एक्सेस करने के लिए या तो टाइप या पूर्णांक का उपयोग कर सकें। क्या आपने अभी तक पूर्णांक के साथ इसे एक्सेस करने की कोशिश की है?


2
जावा में Enums इस तरह से व्यवहार नहीं करते हैं। वे एक स्पष्ट प्रकार हैं।
क्रिस थॉम्पसन

प्रत्येक एनुम ऑब्जेक्ट में एक आंतरिक संख्या होगी (अर्थात वह स्थिति जिसमें इसे घोषित किया गया था), और इसे .ordinal()विधि द्वारा एक्सेस किया जा सकता है । (दूसरा तरीका, उपयोग करें BonusType.values()[i]।) लेकिन ऊपर दिए गए उदाहरण में, यहाँ अनुक्रमणिका और बाहरी मान मेल नहीं खाते।
पाओलो एबरमन

1

बहुत बढ़िया सवाल :-) मैंने कुछ समय पहले Mr.Ferguson`s के समान समाधान का उपयोग किया था। हमारी विघटित एनम इस तरह दिखती है:

final class BonusType extends Enum
{

    private BonusType(String s, int i, int id)
    {
        super(s, i);
        this.id = id;
    }

    public static BonusType[] values()
    {
        BonusType abonustype[];
        int i;
        BonusType abonustype1[];
        System.arraycopy(abonustype = ENUM$VALUES, 0, abonustype1 = new BonusType[i = abonustype.length], 0, i);
        return abonustype1;
    }

    public static BonusType valueOf(String s)
    {
        return (BonusType)Enum.valueOf(BonusType, s);
    }

    public static final BonusType MONTHLY;
    public static final BonusType YEARLY;
    public static final BonusType ONE_OFF;
    public final int id;
    private static final BonusType ENUM$VALUES[];

    static 
    {
        MONTHLY = new BonusType("MONTHLY", 0, 1);
        YEARLY = new BonusType("YEARLY", 1, 2);
        ONE_OFF = new BonusType("ONE_OFF", 2, 3);
        ENUM$VALUES = (new BonusType[] {
            MONTHLY, YEARLY, ONE_OFF
        });
    }
}

यह देखना स्पष्ट है कि ordinal()अस्थिर क्यों है। यह है iमें super(s, i);। मैं भी निराशावादी हूं कि आप इन पहले से गणना किए गए लोगों की तुलना में अधिक सुरुचिपूर्ण समाधान के बारे में सोच सकते हैं। आखिरकार एनम किसी भी अंतिम वर्ग के रूप में कक्षाएं हैं।


1

पूर्णता की खातिर, यहां किसी भी एनम प्रकार से सूचकांक द्वारा एनम मूल्यों को प्राप्त करने के लिए एक सामान्य दृष्टिकोण है। मेरा इरादा Enum.valueOf (क्लास, स्ट्रिंग) की तरह विधि को देखने और महसूस करने का था । फी, मैंने इस विधि को यहाँ से कॉपी किया है

सूचकांक संबंधी मुद्दे (पहले से ही यहां गहराई से चर्चा की गई) अभी भी लागू होते हैं।

/**
 * Returns the {@link Enum} instance for a given ordinal.
 * This method is the index based alternative
 * to {@link Enum#valueOf(Class, String)}, which
 * requires the name of an instance.
 * 
 * @param <E> the enum type
 * @param type the enum class object
 * @param ordinal the index of the enum instance
 * @throws IndexOutOfBoundsException if ordinal < 0 || ordinal >= enums.length
 * @return the enum instance with the given ordinal
 */
public static <E extends Enum<E>> E valueOf(Class<E> type, int ordinal) {
    Preconditions.checkNotNull(type, "Type");
    final E[] enums = type.getEnumConstants();
    Preconditions.checkElementIndex(ordinal, enums.length, "ordinal");
    return enums[ordinal];
}

यह वास्तव में मैं क्या देख रहा हूँ नहीं है, क्योंकि यह केवल अपने क्रमबद्ध द्वारा एनम मूल्यों को प्राप्त करता है, एक निर्दिष्ट पूर्णांक आईडी द्वारा नहीं (अपना प्रश्न देखें)। इसके अलावा, अगर मुझे लगता है कि, मैं बस का उपयोग कर सकते हैं MyEnumType.values()- एक स्थिर सहायक विधि के लिए कोई ज़रूरत नहीं है।
14

0
Int -->String :

public enum Country {

    US("US",0),
    UK("UK",2),
    DE("DE",1);


    private static Map<Integer, String> domainToCountryMapping; 
    private String country;
    private int domain;

    private Country(String country,int domain){
        this.country=country.toUpperCase();
        this.domain=domain;
    }

    public String getCountry(){
        return country;
    }


    public static String getCountry(String domain) {
        if (domainToCountryMapping == null) {
            initMapping();
        }

        if(domainToCountryMapping.get(domain)!=null){
            return domainToCountryMapping.get(domain);
        }else{
            return "US";
        }

    }

     private static void initMapping() {
         domainToCountryMapping = new HashMap<Integer, String>();
            for (Country s : values()) {
                domainToCountryMapping.put(s.domain, s.country);
            }
        }

0

मुझे कुछ अलग चाहिए था क्योंकि मैं एक सामान्य दृष्टिकोण का उपयोग करना चाहता था। मैं बाइट सरणियों से एनम और पढ़ रहा हूँ। यह वह जगह है जहां मैं आता हूं:

public interface EnumConverter {
    public Number convert();
}



public class ByteArrayConverter {
@SuppressWarnings("unchecked")
public static Enum<?> convertToEnum(byte[] values, Class<?> fieldType, NumberSystem numberSystem) throws InvalidDataException {
    if (values == null || values.length == 0) {
        final String message = "The values parameter must contain the value";
        throw new IllegalArgumentException(message);
    }

    if (!dtoFieldType.isEnum()) {
        final String message = "dtoFieldType must be an Enum.";
        throw new IllegalArgumentException(message);
    }

    if (!EnumConverter.class.isAssignableFrom(fieldType)) {
        final String message = "fieldType must implement the EnumConverter interface.";
        throw new IllegalArgumentException(message);
    }

    Enum<?> result = null;
    Integer enumValue = (Integer) convertToType(values, Integer.class, numberSystem); // Our enum's use Integer or Byte for the value field.

    for (Object enumConstant : fieldType.getEnumConstants()) {
        Number ev = ((EnumConverter) enumConstant).convert();

        if (enumValue.equals(ev)) {
            result = (Enum<?>) enumConstant;
            break;
        }
    }

    if (result == null) {
        throw new EnumConstantNotPresentException((Class<? extends Enum>) fieldType, enumValue.toString());
    }

    return result;
}

public static byte[] convertEnumToBytes(Enum<?> value, int requiredLength, NumberSystem numberSystem) throws InvalidDataException {
    if (!(value instanceof EnumConverter)) {
        final String message = "dtoFieldType must implement the EnumConverter interface.";
        throw new IllegalArgumentException(message);
    }

    Number enumValue = ((EnumConverter) value).convert();
    byte[] result = convertToBytes(enumValue, requiredLength, numberSystem);
    return result;
}

public static Object convertToType(byte[] values, Class<?> type, NumberSystem numberSystem) throws InvalidDataException {
    // some logic to convert the byte array supplied by the values param to an Object.
}

public static byte[] convertToBytes(Object value, int requiredLength, NumberSystem numberSystem) throws InvalidDataException {
    // some logic to convert the Object supplied by the'value' param to a byte array.
}
}

एनुम का उदाहरण:

public enum EnumIntegerMock implements EnumConverter {
    VALUE0(0), VALUE1(1), VALUE2(2);

    private final int value;

    private EnumIntegerMock(int value) {
        this.value = value;
    }

public Integer convert() {
    return value;
}

}

public enum EnumByteMock implements EnumConverter {
    VALUE0(0), VALUE1(1), VALUE2(2);

    private final byte value;

    private EnumByteMock(int value) {
        this.value = (byte) value;
    }

    public Byte convert() {
        return value;
    }
}

0

सिर्फ इसलिए कि स्वीकृत उत्तर स्व सम्‍मिलित नहीं है:

समर्थन कोड:

public interface EnumWithCode<E extends Enum<E> & EnumWithCode<E>> {

    public Integer getCode();

    E fromCode(Integer code);
}


public class EnumWithCodeMap<V extends Enum<V> & EnumWithCode<V>> {

    private final HashMap<Integer, V> _map = new HashMap<Integer, V>();

    public EnumWithCodeMap(Class<V> valueType) {
        for( V v : valueType.getEnumConstants() )
            _map.put(v.getCode(), v);
    }

    public V get(Integer num) {
        return _map.get(num);
    }
}

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

public enum State implements EnumWithCode<State> {
    NOT_STARTED(0), STARTED(1), ENDED(2);

    private static final EnumWithCodeMap<State> map = new EnumWithCodeMap<State>(
            State.class);

    private final int code;

    private State(int code) {
        this.code = code;
    }

    @Override
    public Integer getCode() {
        return code;
    }

    @Override
    public State fromCode(Integer code) {
        return map.get(code);
    }

}

0

दिया हुआ:

सार्वजनिक एनम बोनस टाइप {MONTHLY (0), YEARLY (1), ONE_OFF (2)}

बोनस टाइप बोनस = निश्चित रूप से;

System.out.println (Bonus.Ordinal () + ":" + बोनस)

आउटपुट: 1: पूरी तरह से


0

यदि आपके पास एक क्लास कार है

public class Car {
    private Color externalColor;
}

और संपत्ति रंग एक वर्ग है

@Data
public class Color {
    private Integer id;
    private String name;
}

और आप Color को Enum में बदलना चाहते हैं

public class CarDTO {
    private ColorEnum externalColor;
}

बस ColorEnum में रंग बदलने के लिए रंग वर्ग में एक विधि जोड़ें

@Data
public class Color {
    private Integer id;
    private String name;

    public ColorEnum getEnum(){
        ColorEnum.getById(id);
    }
}

और ColorEnum के अंदर विधि getById को लागू करता है ()

public enum ColorEnum {
...
    public static ColorEnum getById(int id) {
        for(ColorEnum e : values()) {
            if(e.id==id) 
                return e;
        }
    }
}

अब आप एक classMap का उपयोग कर सकते हैं

private MapperFactory factory = new DefaultMapperFactory.Builder().build();
...
factory.classMap(Car.class, CarDTO.class)
    .fieldAToB("externalColor.enum","externalColor")
    .byDefault()
    .register();
...
CarDTO dto = mapper.map(car, CarDTO.class);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.