निम्नलिखित में से एनम को जावा में इंट में डालने का सही तरीका क्या है?
public enum MyEnum
{
EnumValue1,
EnumValue2
}
MyEnum enumValue = (MyEnum) x; //Doesn't work???
निम्नलिखित में से एनम को जावा में इंट में डालने का सही तरीका क्या है?
public enum MyEnum
{
EnumValue1,
EnumValue2
}
MyEnum enumValue = (MyEnum) x; //Doesn't work???
जवाबों:
कोशिश करें MyEnum.values()[x]
कि कहाँ x
होना चाहिए 0
या 1
, यानी कि एनम के लिए एक वैध अध्यादेश।
ध्यान दें कि जावा एनम में वास्तव में कक्षाएं हैं (और एनम मान इस प्रकार ऑब्जेक्ट हैं) और इस प्रकार आप एक एनम int
या यहां तक Integer
कि एक एनम भी नहीं डाल सकते हैं ।
MyEnum.values()
इसके महंगे होने को कैश कर सकते हैं । अगर आप इसे सैकड़ों बार कहते हैं।
MyEnum.values()[x]
एक महंगा ऑपरेशन है। यदि प्रदर्शन एक चिंता का विषय है, तो आप कुछ इस तरह से करना चाह सकते हैं:
public enum MyEnum {
EnumValue1,
EnumValue2;
public static MyEnum fromInteger(int x) {
switch(x) {
case 0:
return EnumValue1;
case 1:
return EnumValue2;
}
return null;
}
}
MyEnum.values()[x]
एक महंगे ऑपरेशन के रूप में क्यों मानते हैं । मुझे नहीं पता कि यह विवरण में कैसे काम करता है, लेकिन मेरे लिए ऐसा लगता है कि एरियर में एक तत्व तक पहुंचना कोई बड़ी बात नहीं होगी, निरंतर समय। यदि सरणी का निर्माण करना है तो यह O (n) समय लेता है, जो आपके समाधान के समान रनिंग टाइम है।
values()
हर बार एक नया सरणी उत्पन्न करता है, क्योंकि सरणियाँ परस्पर हैं इसलिए एक ही समय में एक ही बार वापस करना सुरक्षित नहीं होगा। स्विच स्टेटमेंट आवश्यक रूप से O (n) नहीं हैं, उन्हें टेबल जंप करने के लिए संकलित किया जा सकता है। इसलिए लोरेंजो के दावे जायज लगते हैं।
myEnum = myEnumValues[i]
भी i
बिना बदले एनम में वें आइटम को वापस कर देगा ।
यदि आप अपने पूर्णांक मान देना चाहते हैं, तो आप नीचे की तरह एक संरचना का उपयोग कर सकते हैं
public enum A
{
B(0),
C(10),
None(11);
int id;
private A(int i){id = i;}
public int GetID(){return id;}
public boolean IsEmpty(){return this.equals(A.None);}
public boolean Compare(int i){return id == i;}
public static A GetValue(int _id)
{
A[] As = A.values();
for(int i = 0; i < As.length; i++)
{
if(As[i].Compare(_id))
return As[i];
}
return A.None;
}
}
आप इस तरह की कोशिश कर सकते हैं।
एलिमेंट आईडी के साथ क्लास बनाएं।
public Enum MyEnum {
THIS(5),
THAT(16),
THE_OTHER(35);
private int id; // Could be other data type besides int
private MyEnum(int id) {
this.id = id;
}
public static MyEnum fromId(int id) {
for (MyEnum type : values()) {
if (type.getId() == id) {
return type;
}
}
return null;
}
}
अब इंट के रूप में आईडी का उपयोग करके इस एनम को प्राप्त करें।
MyEnum myEnum = MyEnum.fromId(5);
मैं मानों को कैश करता हूं और एक सरल स्टेटिक एक्सेस विधि बनाता हूं:
public static enum EnumAttributeType {
ENUM_1,
ENUM_2;
private static EnumAttributeType[] values = null;
public static EnumAttributeType fromInt(int i) {
if(EnumAttributeType.values == null) {
EnumAttributeType.values = EnumAttributeType.values();
}
return EnumAttributeType.values[i];
}
}
values
को विधि के समान नाम नहीं देते हैं तो IMHO कम भ्रमित होता है values()
। मैं cachedValues
फ़ील्ड नाम के लिए उपयोग करता हूं ।
Java enums में एक ही तरह की Enum-to-int मैपिंग नहीं है जो वे C ++ में करते हैं।
उस ने कहा, सभी enums में एक values
विधि है जो संभावित enum मानों की एक सरणी देता है, इसलिए
MyEnum enumValue = MyEnum.values()[x];
कार्य करना चाहिए। यह थोड़ा बुरा है और यदि संभव हो तो int
एस से Enum
एस (या इसके विपरीत) की कोशिश न करें और परिवर्तित करने के लिए बेहतर हो सकता है।
यह ऐसा कुछ नहीं है जो आमतौर पर किया जाता है, इसलिए मैं पुनर्विचार करूंगा। लेकिन कहा जा रहा है कि, मौलिक संचालन हैं: int -> Enum का उपयोग EnumType.values () [intNum], और enum -> int का उपयोग करते हुए enumInst.ordinal ()।
हालाँकि, मानों के किसी भी क्रियान्वयन () में आपके पास सरणी की एक प्रति देने के अलावा कोई विकल्प नहीं है (जावा सरणियाँ कभी-कभी केवल पढ़ने के लिए नहीं होती हैं), आपको एनुम का उपयोग करने के लिए एनुम -> इंट मैपिंग का उपयोग करना बेहतर होगा।
यहाँ समाधान मैं के साथ जाने की योजना है। यह न केवल गैर-अनुक्रमिक पूर्णांक के साथ काम करता है, बल्कि इसे किसी अन्य डेटा प्रकार के साथ काम करना चाहिए जिसे आप अपने एनम मानों के लिए अंतर्निहित आईडी के रूप में उपयोग करना चाहते हैं।
public Enum MyEnum {
THIS(5),
THAT(16),
THE_OTHER(35);
private int id; // Could be other data type besides int
private MyEnum(int id) {
this.id = id;
}
public int getId() {
return this.id;
}
public static Map<Integer, MyEnum> buildMap() {
Map<Integer, MyEnum> map = new HashMap<Integer, MyEnum>();
MyEnum[] values = MyEnum.values();
for (MyEnum value : values) {
map.put(value.getId(), value);
}
return map;
}
}
मुझे केवल आईडी को विशिष्ट समय पर (जब किसी फ़ाइल से डेटा लोड कर रहा है) एनम में परिवर्तित करने की आवश्यकता है, इसलिए मेरे लिए हर समय मानचित्र को याद में रखने का कोई कारण नहीं है। यदि आपको हर समय मानचित्र की आवश्यकता होती है, तो आप इसे हमेशा अपने Enum वर्ग के स्थिर सदस्य के रूप में कैश कर सकते हैं।
clearCachedValues
जब आप इसका उपयोग कर रहे हों (जो कि निजी क्षेत्र को वापस शून्य पर सेट करता है)। मैं MyEnum.fromInt(i)
एक मानचित्र वस्तु के आसपास से गुजरने को समझने में आसान मानता हूं ।
मामले में यह दूसरों की मदद करता है, जो विकल्प मुझे पसंद है, जो यहां सूचीबद्ध नहीं है, अमरूद की मैप्स कार्यक्षमता का उपयोग करता है :
public enum MyEnum {
OPTION_1(-66),
OPTION_2(32);
private int value;
private MyEnum(final int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
private static ImmutableMap<Integer, MyEnum> reverseLookup =
Maps.uniqueIndex(Arrays.asList(MyEnum.values())), MyEnum::getValue);
public static MyEnum fromInt(final int id) {
return reverseLookup.getOrDefault(id, OPTION_1);
}
}
डिफ़ॉल्ट के साथ आप उपयोग कर सकते हैं null
, तो आप कर सकते हैं throw IllegalArgumentException
या अपने fromInt
एक वापसी कर सकता है Optional
, जो कुछ भी व्यवहार आप पसंद करते हैं।
Map<Integer, MyEnum> reverseLookup = Arrays.stream(MyEnum.values()).collect(Collectors.toMap(MyEnum::getValue, Function.identity()));
getValue()
विधि को भी परिभाषित करना चाह सकते हैं ।
आप values()
enum से अधिक पुनरावृति कर सकते हैं और enum के पूर्णांक मान की तुलना id
नीचे दिए गए तरीके से कर सकते हैं:
public enum TestEnum {
None(0),
Value1(1),
Value2(2),
Value3(3),
Value4(4),
Value5(5);
private final int value;
private TestEnum(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public static TestEnum getEnum(int value){
for (TestEnum e:TestEnum.values()) {
if(e.getValue() == value)
return e;
}
return TestEnum.None;//For values out of enum scope
}
}
और बस इस तरह का उपयोग करें:
TestEnum x = TestEnum.getEnum(4);//Will return TestEnum.Value4
मुझे आशा है कि यह मदद करता है;)
@ChadBefus के उत्तर और @shosel टिप्पणी के आधार पर, मैं इसका उपयोग करने की सलाह दूंगा। (कुशल खोज, और शुद्ध जावा पर काम करता है> = 8)
import java.util.stream.Collectors;
import java.util.function.Function;
import java.util.Map;
import java.util.Arrays;
public enum MyEnum {
OPTION_1(-66),
OPTION_2(32);
private int value;
private MyEnum(final int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
private static Map<Integer, MyEnum> reverseLookup =
Arrays.stream(MyEnum.values()).collect(Collectors.toMap(MyEnum::getValue, Function.identity()));
public static MyEnum fromInt(final int id) {
return reverseLookup.getOrDefault(id, OPTION_1);
}
public static void main(String[] args) {
System.out.println(fromInt(-66).toString());
}
}
एक अच्छा विकल्प है से बचने से रूपांतरण int
करने के लिए enum
() y.ordinal करने के लिए () और बदले एक्स या वाई तदनुसार उदाहरण के लिए, यदि आप अधिक से अधिक मूल्य की जरूरत है, तो आप x.ordinal तुलना कर सकते हैं:। (इस तरह की तुलना को सार्थक बनाने के लिए आपको मूल्यों को फिर से क्रमबद्ध करने की आवश्यकता हो सकती है।)
यदि यह संभव नहीं है, तो मैं MyEnum.values()
एक स्थिर सरणी में संग्रहीत करूंगा ।
यह डॉक्टरों के रूप में एक ही जवाब है लेकिन यह दर्शाता है कि कैसे उत्परिवर्ती सरणियों के साथ समस्या को खत्म करना है। यदि आप शाखा भविष्यवाणी के कारण इस तरह के दृष्टिकोण का उपयोग पहले करते हैं, तो शून्य प्रभाव बहुत कम होगा और पूरे कोड में केवल एक बार परिवर्तनशील सरणी मान () फ़ंक्शन को कॉल किया जाता है। चूंकि दोनों चर स्थिर हैं, वे इस गणना के प्रत्येक उपयोग के लिए n * मेमोरी का उपभोग नहीं करेंगे।
private static boolean arrayCreated = false;
private static RFMsgType[] ArrayOfValues;
public static RFMsgType GetMsgTypeFromValue(int MessageID) {
if (arrayCreated == false) {
ArrayOfValues = RFMsgType.values();
}
for (int i = 0; i < ArrayOfValues.length; i++) {
if (ArrayOfValues[i].MessageIDValue == MessageID) {
return ArrayOfValues[i];
}
}
return RFMsgType.UNKNOWN;
}
enum MyEnum {
A(0),
B(1);
private final int value;
private MyEnum(int val) {this.value = value;}
private static final MyEnum[] values = MyEnum.values();//cache for optimization
public static final getMyEnum(int value) {
try {
return values[value];//OOB might get triggered
} catch (ArrayOutOfBoundsException e) {
} finally {
return myDefaultEnumValue;
}
}
}
कोटलिन में:
enum class Status(val id: Int) {
NEW(0), VISIT(1), IN_WORK(2), FINISHED(3), CANCELLED(4), DUMMY(5);
companion object {
private val statuses = Status.values().associateBy(Status::id)
fun getStatus(id: Int): Status? = statuses[id]
}
}
उपयोग:
val status = Status.getStatus(1)!!
इसे लागू किया। यह लापता मूल्यों, नकारात्मक मूल्यों के लिए अनुमति देता है और कोड को सुसंगत रखता है। नक्शा भी कैश किया गया है। एक इंटरफेस का उपयोग करता है और जावा 8 की जरूरत है।
enum
public enum Command implements OrdinalEnum{
PRINT_FOO(-7),
PRINT_BAR(6),
PRINT_BAZ(4);
private int val;
private Command(int val){
this.val = val;
}
public int getVal(){
return val;
}
private static Map<Integer, Command> map = OrdinalEnum.getValues(Command.class);
public static Command from(int i){
return map.get(i);
}
}
इंटरफेस
public interface OrdinalEnum{
public int getVal();
@SuppressWarnings("unchecked")
static <E extends Enum<E>> Map<Integer, E> getValues(Class<E> clzz){
Map<Integer, E> m = new HashMap<>();
for(Enum<E> e : EnumSet.allOf(clzz))
m.put(((OrdinalEnum)e).getVal(), (E)e);
return m;
}
}