এনাম অর্ডিনাল থেকে এনাম টাইপ রূপান্তর করুন


315

আমি এনাম টাইপ করেছি যা ReportTypeEnumআমার সমস্ত ক্লাসের পদ্ধতির মধ্যে পাস হয় তবে আমার তখন এটি ইউআরএল পাস করতে হবে তাই আমি ইনটাল মান পেতে অর্ডিনাল পদ্ধতিটি ব্যবহার করি। আমি আমার অন্য জেএসপি পৃষ্ঠাতে আসার পরে, আমাকে এটিকে আবার একটিতে রূপান্তর করা দরকার ReportTypeEnumযাতে আমি এটি পাস করা চালিয়ে যেতে পারি।

আমি কীভাবে অর্ডিনালকে রূপান্তর করতে পারি ReportTypeEnum?

জাভা 6 এসই ব্যবহার করে।


1
এখন পর্যন্ত কোনও জাভা 6 ইই নেই, (এএফআইকে)। এখানে জাভা এসই 6, এবং জাভা ইই 5 রয়েছে
হোসাম এলি

উত্তর:


632

কোনও অর্ডিনালকে তার এনম রিপ্রেসেন্টেশনে রূপান্তর করতে আপনি এটি করতে চাইতে পারেন:

ReportTypeEnum value = ReportTypeEnum.values()[ordinal];

অ্যারে সীমানা লক্ষ্য করুন।

মনে রাখবেন যে প্রতিটি কল values()একটি নতুন ক্লোন করা অ্যারে প্রদান করে যা নেতিবাচক উপায়ে কার্য সম্পাদনকে প্রভাবিত করতে পারে। আপনি অ্যারেটিকে ক্যাশে করতে চাইতে পারেন যদি এটি প্রায়শই বলা হয়ে থাকে।

ক্যাশে কীভাবে কোড উদাহরণvalues()


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


আমি এই সমাধানটি কার্যকর করেছি এবং এটি আমার পক্ষে কার্যকর হচ্ছে না। এটি অর্ডিনাল মান প্রদান করে যাতে গণনা করা প্রকারগুলি যোগ করা হয় তার সাথে মেলে গ্যারান্টিযুক্ত নয়। আমি জানি না যে এই উত্তরটি কী পরামর্শ দিচ্ছে, তবে আমি তবুও লোকদের সতর্ক করতে চেয়েছিলাম
IcedDante

@ আইসড্যান্ট: সূত্রের গণ্যমানের ক্রমের সাথে সামঞ্জস্য করার নিশ্চয়ই অরডিনালটি নিশ্চিত। আপনি যদি অন্যরকম আচরণ লক্ষ্য করেন তবে অবশ্যই অন্য কিছু ভুল হতে পারে। অন্যান্য উত্তরগুলিতে বর্ণিত সমস্ত কারণে উপরের আমার উত্তরটি সাবঅস্টিমাল।
জোছিম সউর

137

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

পরিবর্তে (এবং এর মাধ্যমে ডিকোড ) enumব্যবহার করে কেন এনকোড করব না?myEnumValue.name()ReportTypeEnum.valueOf(s)


24
আপনি যদি এনামের নাম পরিবর্তন করেন (তবে ক্রমটি বজায় রাখুন)?
আরনে এভার্টসন

6
@ আর্ন - আমি মনে করি এটি কোনও অনভিজ্ঞ ব্যক্তি আসার চেয়ে valueশুরু বা সঠিক বর্ণানুক্রমিক / যৌক্তিক অবস্থানের যে কোনওটিতে যোগ করার চেয়ে কম সম্ভাবনা রয়েছে । (লজিক্যাল দ্বারা আমি উদাহরণস্বরূপ TimeUnitমানগুলির একটি লজিকাল অবস্থান রয়েছে)
অক্সবো_লাক্স

7
আমি অবশ্যই আমার এনামের নামের চেয়ে এনামদের অর্ডার জোর করতে পছন্দ করি ... এ কারণেই আমি ডাটাবেসে এনামের নাম না রেখে অর্ডিনাল সংরক্ষণ করতে পছন্দ করি। তদ্ব্যতীত,

8
আমি রাজী. একটি পাবলিক এপিআই-তে, এনুমের নাম পরিবর্তন করলে পশ্চাদপটে সামঞ্জস্যতা ভেঙে যায় তবে ক্রম পরিবর্তন করা যায় না। এই কারণে, নামটি আপনার "কী" হিসাবে ব্যবহার করা আরও বেশি
নোয়েল

3
অর্ডিনাল সংরক্ষণ করে আপনার ধারণাগুলি অন্য ভাষায় অনুবাদ করা সহজ করে। আপনার যদি সি তে কিছু উপাদান লেখার দরকার হয়?
কিয়েড

94

যদি আমি values()প্রচুর ব্যবহার করতে যাচ্ছি :

enum Suit {
   Hearts, Diamonds, Spades, Clubs;
   public static final Suit values[] = values();
}

ইতিমধ্যে যেখানেই। জাভা:

Suit suit = Suit.values[ordinal];

আপনার অ্যারে সীমানা মনে।


3
+1 এটি এখন পর্যন্ত সেরা সমাধান আইএমএইচও কারণ বিশেষত android.os.Message- এ কেউ চারপাশে অর্ডিনালগুলি পাস করতে পারে।
লাইজডো

9
এটি অত্যন্ত উদ্বেগজনক কারণ অ্যারেগুলি পরিবর্তনযোগ্য । মানগুলি [] চূড়ান্ত হলেও এটি Suit.values[0] = Suit.Diamonds;আপনার কোডের কোথাও প্রতিরোধ করে না । আদর্শভাবে এটি কখনই ঘটবে না, তবে পরিবর্তনীয় ক্ষেত্রগুলি উন্মোচিত করার সামগ্রিক নীতিটি এখনও ধারণ করে না। এই পদ্ধতির জন্য, Collections.unmodifiableListপরিবর্তে ব্যবহারের মতো বা বিবেচনা করুন।
Mshnik

কীভাবে - ব্যক্তিগত স্ট্যাটিক চূড়ান্ত স্যুট মানগুলি [] = মানগুলি (); পাবলিক স্ট্যাটিক স্যুট [] getValues ​​() {ফেরতের মান; }
প্রত্যুশ

4
@ প্রত্যুষ যে অ্যারে পরিবর্তনশীলকে পরিবর্তনযোগ্য করে তুলবে, তবে এর সামগ্রীগুলি নয়। আমি এখনও getValues ​​() [0] = কিছু করতে পারি;
ক্যালাবাকিন

সম্মত হন, এইভাবে বিষয়টি Suit values[]সরাসরি বা অপ্রত্যক্ষভাবে প্রকাশিত হয় না (কিভাবে এটির মাধ্যমে উল্লেখ করা হয়েছিল getValues()), আমি এমন একটি সার্বজনীন পদ্ধতি নিয়ে কাজ করি যেখানে ordinalমানটি প্রেরণ করতে হবে কীভাবে একটি যুক্তি দিয়ে এবং Suitউপস্থাপনাটি ফিরিয়ে আনতে হবে Suit values[]। এখানে বিন্দুটি (প্রথম থেকেই প্রশ্নের টাইল) একটি এনাম অর্ডিনাল থেকে এনাম টাইপ তৈরি করা হয়েছিল
ম্যানুয়েল জর্ডান

13

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

public enum ReportTypeEnum {
    R1(1),
    R2(2),
    R3(3),
    R4(4),
    R5(5),
    R6(6),
    R7(7),
    R8(8);

    private static Logger log = LoggerFactory.getLogger(ReportEnumType.class);  
    private static Map<Integer, ReportTypeEnum> lookup;
    private Integer dbValue;

    private ReportTypeEnum(Integer dbValue) {
        this.dbValue = dbValue;
    }


    static {
        try {
            ReportTypeEnum[] vals = ReportTypeEnum.values();
            lookup = new HashMap<Integer, ReportTypeEnum>(vals.length);

            for (ReportTypeEnum  rpt: vals)
                lookup.put(rpt.getDbValue(), rpt);
         }
         catch (Exception e) {
             // Careful, if any exception is thrown out of a static block, the class
             // won't be initialized
             log.error("Unexpected exception initializing " + ReportTypeEnum.class, e);
         }
    }

    public static ReportTypeEnum fromDbValue(Integer dbValue) {
        return lookup.get(dbValue);
    }

    public Integer getDbValue() {
        return this.dbValue;
    }

}

এখন আপনি অনুসন্ধান এবং তদ্বিপরীত পরিবর্তন না করে অর্ডার পরিবর্তন করতে পারেন।


এটি সঠিক উত্তর। আমি আরও অবাক হয়েছি অন্যান্য অন্যান্য প্রত্যক্ষ তবে সম্ভাব্য অবৈধ উত্তরগুলির সাথে (ভবিষ্যতে কোড পরিবর্তনের কারণে) এর তুলনায় এটি কয়েকটি পয়েন্ট পেয়েছে।
ক্যালাবাকিন

8

আপনি একটি স্ট্যাটিক লুক টেবিল ব্যবহার করতে পারেন:

public enum Suit {
  spades, hearts, diamonds, clubs;

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

  static{
    int ordinal = 0;
    for (Suit suit : EnumSet.allOf(Suit.class)) {
      lookup.put(ordinal, suit);
      ordinal+= 1;
    }
  }

  public Suit fromOrdinal(int ordinal) {
    return lookup.get(ordinal);
  }
}

3
Enums দেখুন ।
ট্র্যাশগোড

11
কি দারুন! এইমাত্র! এটি অবশ্যই ঝরঝরে, তবে ... আপনি জানেন - আমার ভিতরে থাকা সি প্রোগ্রামার ব্যথা করে চিৎকার করে বলেছিল যে আপনি একটি পূর্ণ-বিকাশযুক্ত হ্যাশম্যাপ বরাদ্দ করেছেন এবং এর ভিতরে লুকআপগুলি সম্পাদন করেন কেবল 4 টি ধ্রুবককে পরিচালনা করার জন্য: স্প্যাডস, হার্টস, হীরা এবং ক্লাব! এসি প্রোগ্রামার প্রতিটি জন্য 1 বাইট বরাদ্দ করবে: 'কনস্ট চর সিএলবিএস = 0;' ইত্যাদি ... হ্যাঁ, একটি হ্যাশম্যাপ লুক হ'ল ও (1), তবে হ্যাশম্যাপের মেমরি এবং সিপিইউ ওভারহেড, এক্ষেত্রে এটিকে মাত্রা। লোকেরা যদি এভাবে লিখেন তবে জাভা এমন একটি মেমরি হোগ!
লেজেক

2
প্রতিটি প্রোগ্রামের জন্য ট্রিপল এ গেমের পারফরম্যান্সের প্রয়োজন হয় না। প্রকার সুরক্ষা, পঠনযোগ্যতা, রক্ষণাবেক্ষণযোগ্যতা, ক্রস প্ল্যাটফর্ম সমর্থন, আবর্জনা সংগ্রহ ইত্যাদির জন্য অনেক ক্ষেত্রে ট্রেডিং মেমরি এবং সিপিইউ ন্যায়সঙ্গত। উচ্চ স্তরের ভাষাগুলি একটি কারণে বিদ্যমান।
জানুয়ারী

3
তবে যদি আপনার মূল সীমাটি সর্বদা থাকে 0...(n-1)তবে একটি অ্যারে কম কোড এবং আরও পঠনযোগ্য; পারফরম্যান্স বৃদ্ধি কেবল একটি বোনাস us private static final Suit[] VALUES = values();এবং public Suit fromOrdinal(int ordinal) { return VALUES[ordinal]; }। অতিরিক্ত সুবিধা: অবিলম্বে অবৈধ অধ্যাদেশগুলিতে ক্র্যাশ হয়ে স্থির হয়ে নীরবে ফিরে আসার চেয়ে। (সর্বদা একটি সুবিধা নয়। তবে প্রায়শই))
টমাস

4

এটিই আমি ব্যবহার করি। আমি উপরের সরল সমাধানের চেয়ে "দক্ষ" এর চেয়ে কম যে ভ্রান্তি করছি তা করি না। এটি যা করে তা হ'ল উপরের দ্রবণটিতে যখন একটি অবৈধ অর্ডিনাল মান ব্যবহৃত হয় তখন "অ্যারেআইন্ডেক্সআউটআউটবাউন্ডস" এর চেয়ে অনেক পরিষ্কার ব্যতিক্রম বার্তা সরবরাহ করা হয়।

এটি এনামসেট জাভাদোক পুনরাবৃত্তিকে তাদের প্রাকৃতিক ক্রমে উপাদানগুলি প্রদান করে তা নির্দিষ্ট করে। এটি সঠিক না হলে একটি দাবি আছে।

JUnit4 টেস্ট এটি কীভাবে ব্যবহৃত হয়েছে তা প্রদর্শন করে।

 /**
 * convert ordinal to Enum
 * @param clzz may not be null
 * @param ordinal
 * @return e with e.ordinal( ) == ordinal
 * @throws IllegalArgumentException if ordinal out of range
 */
public static <E extends Enum<E> > E lookupEnum(Class<E> clzz, int ordinal) {
    EnumSet<E> set = EnumSet.allOf(clzz);
    if (ordinal < set.size()) {
        Iterator<E> iter = set.iterator();
        for (int i = 0; i < ordinal; i++) {
            iter.next();
        }
        E rval = iter.next();
        assert(rval.ordinal() == ordinal);
        return rval;
    }
    throw new IllegalArgumentException("Invalid value " + ordinal + " for " + clzz.getName( ) + ", must be < " + set.size());
}

@Test
public void lookupTest( ) {
    java.util.concurrent.TimeUnit tu = lookupEnum(TimeUnit.class, 3);
    System.out.println(tu);
}

1

প্রগার্ড দিয়ে আমি অ্যান্ড্রয়েডে এটি করি:

public enum SomeStatus {
    UNINITIALIZED, STATUS_1, RESERVED_1, STATUS_2, RESERVED_2, STATUS_3;//do not change order

    private static SomeStatus[] values = null;
    public static SomeStatus fromInteger(int i) {
        if(SomeStatus.values == null) {
            SomeStatus.values = SomeStatus.values();
        }
        if (i < 0) return SomeStatus.values[0];
        if (i >= SomeStatus.values.length) return SomeStatus.values[0];
        return SomeStatus.values[i];
    }
}

এটি সংক্ষিপ্ত এবং প্রোগার্ডে ব্যতিক্রম সম্পর্কে আমার চিন্তা করার দরকার নেই


1

আপনি একটি সহজ পদ্ধতি যেমন সংজ্ঞা দিতে পারেন:

public enum Alphabet{
    A,B,C,D;

    public static Alphabet get(int index){
        return Alphabet.values()[index];
    }
}

এবং এটি ব্যবহার করুন:

System.out.println(Alphabet.get(2));

0
public enum Suit implements java.io.Serializable, Comparable<Suit>{
  spades, hearts, diamonds, clubs;
  private static final Suit [] lookup  = Suit.values();
  public Suit fromOrdinal(int ordinal) {
    if(ordinal< 1 || ordinal> 3) return null;
    return lookup[value-1];
  }
}

পরীক্ষা ক্লাস

public class MainTest {
    public static void main(String[] args) {
        Suit d3 = Suit.diamonds;
        Suit d3Test = Suit.fromOrdinal(2);
        if(d3.equals(d3Test)){
            System.out.println("Susses");
        }else System.out.println("Fails");
    }
}

আমি প্রশংসা করি যে আপনি যদি আমাদের সাথে আরও দক্ষ কোড থাকে তবে আপনি আমাদের সাথে ভাগ করে নিচ্ছেন, আমার এনামটি বিশাল এবং অবিচ্ছিন্নভাবে হাজার বার বলা হয়ে থাকে।


আমি মনে করি আপনি "যদি (অর্ডিনাল <1 || অর্ডিনাল> 4) প্রত্যাবর্তন শূন্য;"
জিওয়ার

0

সুতরাং একটি উপায় হ'ল ExampleEnum valueOfOrdinal = ExampleEnum.values()[ordinal];যা কাজ করে এবং এটি সহজ, তবে আগেই উল্লিখিত হিসাবে, ExampleEnum.values()প্রতিটি কলের জন্য একটি নতুন ক্লোনযুক্ত অ্যারে প্রদান করে। এটি অহেতুক ব্যয়বহুল হতে পারে। আমরা যেমন অ্যারে ক্যাশে করে তা সমাধান করতে পারি ExampleEnum[] values = values()। আমাদের ক্যাশেড অ্যারেটিকে সংশোধন করার অনুমতি দেওয়াও "বিপজ্জনক"। কেউ লিখতে পারে ExampleEnum.values[0] = ExampleEnum.type2;তাই আমি অতিরিক্ত এটি অনুলিপি না করে এমন একটি অ্যাক্সেসর পদ্ধতিতে এটিকে ব্যক্তিগত করে তুলব।

private enum ExampleEnum{
    type0, type1, type2, type3;
    private static final ExampleEnum[] values = values();
    public static ExampleEnum value(int ord) {
        return values[ord];
    }
}

আপনি ExampleEnum.value(ordinal)এনাম মানটির সাথে যুক্ত হতে ব্যবহার করবেনordinal


-1

প্রতিটি এনামের নাম () থাকে, যা এনাম সদস্যের নামের সাথে একটি স্ট্রিং দেয়।

দেওয়া হয়েছে enum Suit{Heart, Spade, Club, Diamond}, Suit.Heart.name()দিবে Heart

প্রতিটি এনামের valueOf()বিপরীত ক্রিয়াকলাপ সম্পাদনের জন্য একটি পদ্ধতি থাকে, যা এনাম টাইপ এবং স্ট্রিং নেয়:

Enum.valueOf(Suit.class, "Heart") আয় Suit.Heart

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


2
কারণ ইন্টিজারের সাথে তুলনা করা স্ট্রিংগুলির তুলনায় অনেক দ্রুত?
হাইকম্যান্ডার 4

2
তবে কেউ এনামকে সংশোধন করে (অধ্যয়ন / পুনরায় ক্রম অনুসারে স্মরণকারী) পরিবর্তন করতে পারবেন। কখনও কখনও এটি সুরক্ষা এবং গতি সম্পর্কে নয়, বিশেষত একটি জেএসপি পৃষ্ঠায় যেখানে নেটওয়ার্কের ল্যাটেন্সিটি একটি পূর্ণসংখ্যার অ্যারের (একটি স্ট্রিং) এবং একটি একক পূর্ণসংখ্যার তুলনা করার মধ্যে পার্থক্যকে 1,000,000 বার করে।
টনি বেনব্রাহিম

ট্যাস্ট্রিং ওভাররাইড করা যেতে পারে, তাই এটি এনামের নামটি না ফেরায়। পদ্ধতির নাম () এটি
এনামের

কোড মন্তব্য এবং অ্যাপ্লিকেশন সংস্করণগুলিও একটি জিনিস (সম্ভবত কোনও ফাইলের ফর্ম্যাটটি সহজ এবং আরও ছোট)
জো পেলিটার

অক্সবো_লাকসের জবাবের মতো একই জিনিসটি যখন মূলত একই জিনিসটির সুপারিশ করা হয় তখন কেন এটিকে কম দেওয়া হয়েছিল তা নিশ্চিত নন। অর্ডিনাল ব্যবহারের চেয়ে অবশ্যই নিরাপদ।
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.