জাভাতে এনট টু এনাস্ট করুন


331

নীচের এনামটি দিয়ে জাভাতে কোনও এনম টু প্রবেশের সঠিক উপায় কী?

public enum MyEnum
{
    EnumValue1,
    EnumValue2
}


MyEnum enumValue = (MyEnum) x; //Doesn't work???

@RyuS। এটি এই প্রশ্নের সদৃশ নয়,
মার্ক রোটভেল

উত্তর:


583

MyEnum.values()[x]যেখানে xঅবশ্যই হবে তা চেষ্টা করুন 0বা 1সেই এনামের জন্য একটি বৈধ অর্ডিনাল।

নোট করুন যে জাভা এনামগুলিতে প্রকৃতপক্ষে ক্লাস (এবং এনাম মানগুলি অবজেক্টস হিসাবে থাকে) এবং সুতরাং আপনি একটি এনাম intবা একটি এমনকি কাস্ট করতে পারবেন না Integer


115
+1: আপনি MyEnum.values()এটি ব্যয়বহুল হিসাবে ক্যাশে করতে চাইতে পারেন । অর্থ্যাৎ আপনি যদি এটি কয়েকবার কল করেন।
পিটার লরে

6
@ পিটারলাওয়ারি সম্পূর্ণতার জন্য, আপনি কেন এটি ধীর হতে হবে তা ব্যাখ্যা করতে পারেন? আমি এর কোন সুস্পষ্ট কারণ দেখছি না।
তারাসাচ

48
@ অ্যারেগুলি পরিবর্তনযোগ্য হিসাবে @ ট্র্যাশচ, মানগুলি () অবশ্যই পরিবর্তন করার ক্ষেত্রে যদি উপাদানগুলির অ্যারের একটি অনুলিপি ফিরে আসে। প্রতিবার এই অনুলিপি তৈরি করা তুলনামূলকভাবে ব্যয়বহুল।
পিটার লরি

9
@ পিটারলাউরে আমি ইদানীং অনেক হ্যাশেল ব্যবহার করেছি (যেখানে সবকিছুই অপরিবর্তনীয়)! আপনার পরিষ্কার এবং সংক্ষিপ্ত ব্যাখ্যার জন্য ধন্যবাদ। :)
তারাসাচ

কিভাবে 'এক্স' পেতে?
বিয়িং জে কে

160

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;
    }
}

44
আপনি যদি স্যুইচ রক্ষণাবেক্ষণ এড়াতে চান, তবে ব্যবহারের ক্লাসে: বেসরকারী ফাইনাল মাইইনাম [] myEnumValues ​​= MyEnum.values ​​(); তারপরে ব্যবহার: myEnum = myEnumValues ​​[i];
গিলি নাচুম

23
@ গিলিনাচুম এটি একটি অদ্ভুত উপায়ে বলেছেন, তবে এই সমাধানের সমস্যাটি রক্ষণাবেক্ষণযোগ্যতা is এটি ডিআরওয়াই নীতির বিরুদ্ধে যায়, যার অর্থ যখনই এনাম মানগুলি পরিবর্তন করা হয় (পুনরায় সাজানো, মান (গুলি) যোগ করা হয়, মান (গুলি) সরানো হয়) একই সাথে স্যুইচ বিবৃতিটি আপডেট করতে হবে। গিলির মন্তব্য জাভাটিকে এনাম মানগুলির তালিকার সাথে সামঞ্জস্য বজায় রাখতে বাধ্য করে, এনাম মানগুলিতে পরিবর্তনগুলি সেই পদ্ধতির কোনও প্রভাব ফেলবে না।
ডান্ড্রে অ্যালিসন

3
@ লোরেঞ্জো পোলিডোরি, আপনি কেন MyEnum.values()[x]একটি ব্যয়বহুল অপারেশন হিসাবে বিবেচনা করছেন তা ব্যাখ্যা করতে পারেন । এটি বিশদে কীভাবে কাজ করে তা আমি জানি না, তবে আমার কাছে মনে হচ্ছে অ্যারেতে কোনও উপাদান অ্যাক্সেস করা কোনও বড় বিষয় হবে না, ওরফে ধ্রুবক সময়। অ্যারেটি বানাতে হলে এটি ও (এন) সময় নেয় যা আপনার সমাধানের মতো একই চলমান সময়।
brunsgaard

1
@ ব্রুনসগার্ড আমি ধরে নিয়েছি values()প্রতিবার একটি নতুন অ্যারে জেনারেট হয়েছে, কারণ অ্যারেগুলি পারস্পরিক পরিবর্তনযোগ্য তাই একাধিকবার একইরকম ফিরে আসা নিরাপদ হবে না। স্যুইচ স্টেটমেন্টগুলি অগত্যা ও (এন) নয়, সেগুলি টেবিলগুলি লাফাতে সংকলিত হতে পারে। সুতরাং লরেনজোর দাবিগুলি ন্যায়সঙ্গত বলে মনে হচ্ছে।
মাইকএফএ

1
@ জনসন গিলির সংস্করণে এনাম ঘোষণার পরিবর্তনের বাইরে কোনও অতিরিক্ত কোড পরিবর্তন দরকার নেই require আপনি যদি এনামে কোনও নতুন আইটেম যুক্ত করেন তবে myEnum = myEnumValues[i]তবুও এনামের iআইটেমটি কোনও পরিবর্তন ছাড়াই ফিরিয়ে দেবেন ।
ডান্ড্রে অ্যালিসন

45

আপনি যদি নিজের পূর্ণসংখ্যার মান দিতে চান তবে নীচের মতো কাঠামো ব্যবহার করতে পারেন

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;
        }
}

5
+1 কারণ এটি সত্যটি হাইলাইট করে, মানগুলি ক্রমাগত হতে হবে না।
havাকা

এছাড়াও, এটি কেবলমাত্র উত্তর বলে মনে হয় যদি আপনি 0 থেকে ডিফল্ট অর্ডিনালগুলি ব্যবহার করার চেয়ে পূর্ণসংখ্যার মানগুলির একটি স্পার (বা পুনরাবৃত্তি) সেট চান (গণনা -১) works যদি আপনি বিদ্যমান কোড যেমন কোনও নেটওয়ার্কের মাধ্যমে ইন্টারঅ্যাক্ট করেন তবে এটি গুরুত্বপূর্ণ হতে পারে।
বেনকসি

উপরোক্ত উত্তরের মতো, মূল্যগুলির ফলাফলের ক্যাশে করা (সম্ভবত) সার্থক, যাতে প্রতিবার আপনি যখন অনুরোধ করেন তখন মেমরির বরাদ্দ এবং অ্যারেকপিটি এড়ানো যায় না Wor
বেনকিসি

1
এবং, আপনার এনামের দৈর্ঘ্যের উপর নির্ভর করে আপনি প্রতিবার রৈখিক অনুসন্ধানের চেয়ে আপনি একটি হ্যাশম্যাপ তৈরি করতে পারেন বা এই অনুসন্ধানের জন্য বাইনারি অনুসন্ধান বা কিছু ব্যবহার করতে পারেন।
বেনকিসি

2
এনটকে এনামে রূপান্তর করার জন্য এটি সঠিক উপায় এবং সর্বোত্তম অনুশীলন হওয়া উচিত এবং আমি মনে করি আপনি পাবলিক স্ট্যাটিক এ গেটভ্যালু (ইন্ট _আইডি) (এর জন্য (এএ: এভালিউস () {যদি (a.getId ( ) == _ আইডি) {রিটার্ন এ;} n নাল রিটার্ন; the কিছু থেকে মুক্তি পান না, ইম্পটি () এবং () স্টাফ তুলনা করুন
ক্রিস.জু

35

আপনি এই মত চেষ্টা করতে পারেন।
এলিমেন্ট আইডি সহ ক্লাস তৈরি করুন।

      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;
            }
      }

এখন int হিসাবে আইডি ব্যবহার করে এই এনামটি আনুন।

MyEnum myEnum = MyEnum.fromId(5);

19

আমি মানগুলি ক্যাশে করি এবং একটি সাধারণ স্ট্যাটিক অ্যাক্সেস পদ্ধতি তৈরি করি:

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];
    }
}

4
এটি আমি এখন ব্যবহার সমাধান। তবে আইএমএইচও যদি আপনি ক্ষেত্রটিকে valuesপদ্ধতির মতো একই নাম না দেন তবে এটি কম বিভ্রান্তিকর values()। আমি cachedValuesমাঠের নাম ব্যবহার করি ।
টুলমেকারস্টেভ

2
দক্ষ এবং মার্জিত; অনুলিপি করা হয়েছে এবং আমার প্রকল্পে আটকানো হয়েছে :) কেবলমাত্র আমি পরিবর্তিত হ'ল ইনট (ইনট আই), যা আমি কেবল (ইনট আই) থেকে ডেকেছি কারণ স্বাক্ষরটিতে দু'বার অন্তর্ভুক্ত করা কিছুটা অপ্রয়োজনীয়।
পাইপড্রিমবম্ব

1
কেন শুরু থেকে শুরু হচ্ছে না? কেন প্রথম হিটের অপেক্ষায়?
কায়সার

9

জাভা এনামগুলিতে সি এন ++-তে একই ধরণের এনাম-টু-ইন ম্যাপিং নেই।

এটি বলেছিল যে সমস্ত এনামের একটি valuesপদ্ধতি রয়েছে যা সম্ভব এনুম মানগুলির একটি অ্যারে প্রদান করে

MyEnum enumValue = MyEnum.values()[x];

কাজ করা উচিত. এটি কিছুটা বাজে এবং সম্ভবত সম্ভব হলে intগুলি থেকে Enumগুলি (বা বিপরীতে) রূপান্তর না করাই ভাল ।


9

এটি এমন কিছু না যা সাধারণত করা হয়, তাই আমি পুনর্বিবেচনা করব। তবে এই কথাটি বলার পরেও, মৌলিক ক্রিয়াকলাপগুলি হ'ল: int -> enum EnumType.values ​​() [intNum] ব্যবহার করে, এবং enumInst.ordinal () ব্যবহার করে enum -> int।

তবে, যেহেতু মানগুলির কোনও প্রয়োগকরণের জন্য আপনাকে অ্যারের একটি অনুলিপি দেওয়ার আগে (জাভা অ্যারেগুলি কেবল পঠনযোগ্য হয় না), আপনাকে এনাম -> ইন্ট ম্যাপিংয়ের ক্যাশে একটি এনামম্যাপ ব্যবহার করে আরও ভাল পরিবেশিত হবে।


2
পুনরায় "এটি এমন কিছু নয় যা সাধারণত করা হয়": সাধারণ ক্ষেত্রে যেখানে এটি কার্যকর হয়: এনাম একটি ডাটাবেসে সঞ্চিত অন্তর্গত মানগুলির সাথে সম্পর্কিত।
টুলমেকারস্টেভ

@ টুলমেকারস্টিভ আপনি একেবারে ঠিক বলেছেন যে ম্যাপিংগুলি প্রয়োজনীয়। তবে আপনি কি কিছু ওআর ম্যাপার বা কিছু সরঞ্জামকিট / লাইব্রেরিতে এই ধরণের এনকোডিংটি ছেড়ে যেতে চান?
দিলুম রানাতুঙ্গা


6

আমি যে সমাধানটি সাথে যেতে চাই তা এখানে Here এটি কেবল অ-অনুক্রমিক পূর্ণসংখ্যার সাথেই কাজ করে না তবে এটি আপনার এনাম মানগুলির জন্য অন্তর্নিহিত আইডি হিসাবে ব্যবহার করতে চাইলে অন্য কোনও ডেটা টাইপের সাথে কাজ করে।

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;
    }
}

আমার নির্দিষ্ট আইডিগুলিতে কেবলমাত্র এনডিগুলিতে এনামগুলিতে রূপান্তর করতে হবে (কোনও ফাইল থেকে ডেটা লোড করার সময়), তাই ম্যাপকে সর্বদা স্মৃতিতে রাখার কোনও কারণ নেই। আপনার যদি মানচিত্রটি সর্বদা অ্যাক্সেসযোগ্য হওয়ার প্রয়োজন হয় তবে আপনি সর্বদা এটি আপনার এনাম শ্রেণীর স্থিতিশীল সদস্য হিসাবে ক্যাশে রাখতে পারেন।


আইএমএইচও যদি আমি মেমরির ব্যবহার সম্পর্কে উদ্বিগ্ন হয়ে থাকি তবে আমি গতিশীলভাবে হ্যাশম্যাপ তৈরি করতাম - @ ফ্যাসিসের মতো কিন্তু বিভিন্ন কোড সহ যখন ক্যাশে নਾਲ হয়, তারপরে clearCachedValuesআপনি এটি ব্যবহার করার পরে একটি দ্বিতীয় পদ্ধতি যুক্ত করুন (এটি ব্যক্তিগত ক্ষেত্রটি শূন্যে ফিরে আসে)। আমি MyEnum.fromInt(i)মানচিত্রের অবজেক্টের চারপাশে যাওয়ার চেয়ে বোঝা সহজ মনে করি ।
টুলমেকারস্টেভ

6

যদি এটি অন্যকে সহায়তা করে তবে আমি যে বিকল্পটি পছন্দ করি তা এখানে লিখিত নয়, যা পেয়ারার মানচিত্রের কার্যকারিতা ব্যবহার করে :

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করতে পারেন returnOptional


3
আপনার উল্লেখ করা উচিত আপনি পেয়ারা ব্যবহার করছেন। বা আপনি স্ট্রিম ব্যবহার করতে পারেন:Map<Integer, MyEnum> reverseLookup = Arrays.stream(MyEnum.values()).collect(Collectors.toMap(MyEnum::getValue, Function.identity()));
shmosel

1
একটি getValue()পদ্ধতিও সংজ্ঞায়িত করতে পারে ।
shmosel

@ শ্মোসেল ওফস, ধন্যবাদ ভ্যালু ফাংশনটি মিস করেছি। জেনেরিক সংস্করণগুলি স্ট্যাকওভারফ্লোতে টাইপ করা সর্বদা প্যান আউট হয় না। লিঙ্কের সাথে পেয়ারা ব্যবহার সম্পর্কে মন্তব্য যুক্ত করা হয়েছে। স্ট্রিমগুলিতে পেয়ারা পদ্ধতি পছন্দ করুন।
চাদ বেফাস

3

আপনি values()এনামের উপরে পুনরাবৃত্তি করতে পারেন এবং 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
আমি আশা করি এটি সাহায্য করে;)


3

@ চ্যাডবিফাসের উত্তর এবং @ শমোসেল মন্তব্যের ভিত্তিতে আমি এটি ব্যবহার করার পরামর্শ দিচ্ছি। (দক্ষ অনুসন্ধান এবং খাঁটি জাভা> = 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());
    }
}

0

একটি ভালো বিকল্প হয় এড়ানোর থেকে রুপান্তরের intজন্যenum () y.ordinal করার () এবং বিনিময়ে X অথবা Y সঙ্গতিপূর্ণভাবেই উদাহরণস্বরূপ, যদি আপনি সর্বোচ্চ মান, আপনি x.ordinal তুলনা করতে পারেন:। (এই ধরণের তুলনাকে অর্থবহ করার জন্য আপনাকে পুনরায় অর্ডার দেওয়ার দরকার হতে পারে))

যদি এটি সম্ভব না হয় তবে আমি MyEnum.values()একটি স্ট্যাটিক অ্যারেতে সংরক্ষণ করব।


1
আপনি যদি ডিবি থেকে প্রাপ্ত হন এবং এটিকে এনামে রূপান্তর করতে চান যা আমি মনে করি এটি একটি সাধারণ কাজ, আপনার প্রয়োজন -> এনাম রূপান্তর, আইএমও ..
ইউকি ইনোই

0

এটি ডাক্তারদের মতো একই উত্তর তবে এটি দেখায় যে কীভাবে পরিবর্তনীয় অ্যারেগুলি দিয়ে সমস্যাটি দূর করা যায়। আপনি যদি শাখার পূর্বাভাসের কারণে প্রথমে এই ধরণের পদ্ধতির ব্যবহার করেন তবে যদি খুব কম থেকে শূন্য প্রভাব থাকে এবং পুরো কোডটি কেবলমাত্র একবার পরিবর্তিত অ্যারে মান () ফাংশন কল করে। উভয় ভেরিয়েবল স্থিতিশীল হওয়ায় তারা এই সংখ্যাটির প্রতিটি ব্যবহারের জন্যও এন * মেমরি গ্রহণ করবে না।

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;
}

0
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;
        }
    }
}


@ শ্মোসেল আমি বিশ্বাস করি ব্যতিক্রমগুলি অপেক্ষাকৃত খুব কম হলে ব্যতিক্রমগুলি উল্লেখযোগ্যভাবে ভাল।
জোসো

আপনার বিশ্বাস ভিত্তিক কি?
shmosel

0

কোটলিনে:

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)!!

0

এই বাস্তবায়ন লিখেছেন। এটি অনুপস্থিত মান, নেতিবাচক মানগুলির জন্য এবং কোডটিকে সঙ্গতিপূর্ণ রাখার অনুমতি দেয়। মানচিত্রটি পাশাপাশি ক্যাশে করা হয়েছে। একটি ইন্টারফেস ব্যবহার করে এবং জাভা 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;
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.