সুবিধাজনকভাবে এনাম এবং ইন্ট / স্ট্রিংয়ের মধ্যে মানচিত্র


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

তারপরে আমি ইনট মানটি অ্যাক্সেস করতে পারি BonusType x = MONTHLY; int id = x.id;

যাইহোক, আমি বিপরীত জন্য কোনও ভাল উপায় দেখতে পাচ্ছি না, অর্থাত্ int থেকে enum যেতে। আদর্শভাবে, কিছু

BonusType bt = BonusType.getById(2); 

আমি যে সমাধানগুলি নিয়ে আসতে পারলাম সেগুলি হ'ল:

  • এনামের মধ্যে একটি অনুসন্ধানের পদ্ধতি রাখুন যা BonusType.values()"ইনট -> এনাম" মানচিত্রটি পূরণ করে, তারপরে এটি ক্যাশে করে এবং এটি দেখার জন্য ব্যবহার করে। কাজ করবে, তবে আমি ব্যবহার করা প্রতিটি এনামে এই পদ্ধতিটি অনুলিপি করতে হবে :-(।
  • স্ট্যাটিক ইউটিলিটি ক্লাসে লুকিং পদ্ধতিটি রাখুন। তারপরে আমার কেবল একটি "অনুসন্ধান" পদ্ধতি প্রয়োজন, তবে এটি একটি স্বেচ্ছাসেবীর এনামের জন্য কাজ করার জন্য প্রতিবিম্বের সাথে আমার বেড়াতে হবে।

উভয় পদ্ধতিই এ জাতীয় সাধারণ (?) সমস্যার জন্য মারাত্মক বিশ্রী মনে হয়।

অন্য কোন ধারণা / অন্তর্দৃষ্টি?


1
আমি <3 জাভা enums কিন্তু ঠিক এই কারণে তাদের ঘৃণা! এগুলি সবসময়ই মনে হয় যে তারা সত্যিই কুৎসিত ত্রুটিগুলি বাদ দিয়ে নিখুঁত ...
ক্রিস থমসন

8
এনাম-> ইন্টের জন্য আপনি কেবল ব্যবহার করতে পারেনordinal()
ডেভিন

1
আপনার আইডি-মানগুলি কি আপনার দ্বারা নির্ধারিত হয় (অর্থাত, আপনি কেবল ব্যবহার করতে পারেন না .ordinal()), বা সেগুলি বাইরের বাহিনী দ্বারা সিদ্ধান্ত নেওয়া হয়?
পাওলো ইবারম্যান

2
@ ডেভিন: হ্যাঁ, এবং কেউ আপনার এনাম ঘোষণাকে পুনরায় সাজিয়েছে বা মাঝখানে কোনও মান মুছে ফেলবে সেই মুহুর্তে আপনার কোডটি ভেঙে দিন। আমি ভীত যে এটি একটি শক্ত সমাধান নয়: - /।
sleske

1
@ অর্ডিনাল () ব্যবহার করে ড্যাভিন যখনই সম্ভব এড়ানো উচিত, এটি ভাষার স্পেসিফিকেশনে রয়েছে
ডিপিএম

উত্তর:


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

এই সমাধানটি দুর্দান্ত এবং 'প্রতিবিম্বের সাথে ফিডিং' প্রয়োজন হয় না কারণ এটি এনাম ইন্টারফেসের সমস্ত এনাম প্রকারের অন্তর্নিহিত সত্যের উপর ভিত্তি করে।


এটি কি অর্ডিনাল ব্যবহার করে না? স্যালসেক একটি আইডি ব্যবহার করেন কারণ এনাম মানগুলি পুনরায় সাজানো হলে নিয়মিত পরিবর্তন হয়।
এক্সারেনন

না, এটি অর্ডিনাল ব্যবহার করে না। এটি একটি সুস্পষ্টভাবে সংজ্ঞায়িত মান মানের উপর নির্ভর করে। মানসিক কী হিসাবে (ভি। কনভার্ট () দ্বারা প্রত্যাবর্তন করা হয়েছে) সেই মান মানটি ব্যবহৃত হয়।
জেফ

2
আমি এই সমাধানটি সত্যিই পছন্দ করি; মনে হয় এটি আপনি পেতে পারেন সবচেয়ে সাধারণ।
sleske

+1 টি। আমার একমাত্র নোটটি হ'ল Numberপরিবর্তে আমি ব্যবহার Byteকরব কারণ আমার ব্যাকিং মানটি আকারে আরও বড় হতে পারে।
Ivaylo স্লাভভ

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

327

enum → int

yourEnum.ordinal()

int → enum

EnumType.values()[someInt]

স্ট্রিং → এনাম

EnumType.valueOf(yourString)

enum → স্ট্রিং

yourEnum.name()

একটি পার্শ্ব-নোট:
আপনি সঠিকভাবে উল্লেখ করেছেন, এটি ordinal()সংস্করণ থেকে সংস্করণে "অস্থির" হতে পারে। আমি সর্বদা আমার ডাটাবেসে স্ট্রিং হিসাবে ধ্রুবক সঞ্চয় করি কেন এটি ঠিক কারণ। (আসলে, মাইএসকিউএল ব্যবহার করার সময় আমি এগুলিকে মাইএসকিএল এনাম হিসাবে সংরক্ষণ করি !)


2
+1 এটি সুস্পষ্ট সঠিক উত্তর। তবে লক্ষ করুন, মানটির জন্য একটি একক আর্গুমেন্ট পদ্ধতি রয়েছে যা কেবল একটি স্ট্রিং নেয় এবং যতক্ষণ না আপনি কংক্রিট এনাম টাইপ ব্যবহার করেন (যেমন BonusType.valueOf("MONTHLY"))
টিম বেন্ডার

18
ordinal()আমাকে সমস্যার সমাধান হিসাবে স্ট্রাইক ব্যবহার করে, কারণ এনাম মানগুলির তালিকাটি পুনরায় সাজানো বা কোনও মান মুছে ফেলা হলে তা ভেঙে যায়। এছাড়াও, এটি কেবলমাত্র ব্যবহারিক যদি মান মান 0 ... এন হয় (যা আমি প্রায়শই কেস হিসাবে পাইনি)।
sleske

4
@ সেলসেক, যদি আপনি যেভাবেই বিদ্যমান থাকা ডেটা নিয়ে সমস্যায় পড়ে থাকেন তবে ধ্রুবকগুলি মুছতে শুরু করেন। (এই বিষয়ে আমার উত্তর আপডেট করুন))
আইওব

3
values()অ্যারে ব্যবহার করা কেবল তখনই কাজ করবে যদি আপনার সমস্ত মানগুলি তাদের আইডির জন্য 0 সূচী হয় এবং ক্রম হিসাবে ঘোষিত হয়। (আপনি যদি এটি ঘোষণা FOO(0), BAR(2), BAZ(1);করেন values[1] == BARএবং values[2] == BAZ
এইচআইডিগুলি

2
@ গ্লোকোডার, অবশ্যই, পূর্ণসংখ্যার যুক্তি কেবল এনাম-অবজেক্টের ক্ষেত্র। এনাম অবজেক্টের সাথে জড়িত অর্ডিনাল ধ্রুবকের সাথে এর কোনও যোগসূত্র নেই (এটি ঠিক তেমন একটিও হতে পারে double)।
আইয়ুব

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 (স্থিতি.ক্লাস) / স্ট্যাটাস.ভেলুয়েস ()
জেলিনসন

8

জাভা 8 প্রকাশের সাথে এই প্রশ্নের উত্তর (গুলি) পুরানো বলে মনে হচ্ছে।

  1. অর্ডিনাল হিসাবে ব্যবহার করবেন না যেমন অর্ডিনাল অস্থির হয় যদি জেভিএম এর বাইরে যেমন একটি ডাটাবেস ধরে থাকে।
  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?
আদম মিশালিক

হ্যাঁ, আমি পেয়ারা ব্যবহার করে এমন কোনও সহায়ক শ্রেণীর কাছ থেকে এটি গ্রহণ করেছি যা শূন্যকে পরিচয় রূপান্তরিত করে।
জন মেয়ার 21

এটি জাভা 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
টার্ড ফার্গুসনের জবাবের মতোই, এটাই যে অপ্রয়োজনীয় সমাধান আমি এড়াতে / উন্নতি করতে চাই ...
sleske

আমি যখন প্রতিবার আইডি দিয়ে কোনও মান জিজ্ঞাসা করি তখন আমি সাধারণত একটি স্ট্যাটিক}} ব্লকে বিপরীত ম্যাপিংগুলি তৈরি করি। আমি স্ট্রিংস (ওপি-র প্রশ্নের অংশ হিসাবেও) ইতিমধ্যে সেখানে ভ্যালুঅফ (স্ট্রিং) পদ্ধতির মতো কিছুটা প্রদর্শিত হওয়ার জন্য আমি সাধারণত পদ্ধতিটি মান ওওফ (ইনট্রি) বলি। কিছুটা কার্যকর জাভাতে আইটেমের মতো: tinyurl.com/4ffvc38
ফ্রেডরিক

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

@ গু্লোকোডার ওয়েল, একাধিকবার পুনরাবৃত্তি না করার অর্থ এই যে আপনি প্রতি সেকেন্ডে কয়েক হাজার বার এটি ব্যবহার করলে তাতে কিছু আসে যায় না যেখানে এটি খুব গুরুত্বপূর্ণ সমস্যা হতে পারে বা কেবল একবার দু'বার কল করে।
ফ্রেডরিক

@ ফ্রেড্রিক আমি স্বীকার করব যে এমন সময় রয়েছে যেখানে অনুকূলিতকরণের প্রয়োজন হতে পারে। আমি এটিও বলছি যে এটি সনাক্ত করা পারফরম্যান্সের সমস্যা না হওয়া পর্যন্ত এটির জন্য অনুকূলিত হন না।
কর্সিকা

2

উভয়ই .ordinal()এবং values()[i]অস্থির কারণ তারা এনামগুলির ক্রমের সাথে নির্ভরশীল। সুতরাং আপনি যদি এনামগুলির ক্রম পরিবর্তন করেন বা কিছু যুক্ত / মুছলে আপনার প্রোগ্রামটি ভেঙে যায়।

এনাম এবং ইন্টের মধ্যে মানচিত্রের জন্য এখানে একটি সহজ তবে কার্যকর পদ্ধতি।

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

স্ট্রিংয়ের জন্য এটি প্রয়োগ করা কঠিন হওয়া উচিত নয়।


হ্যাঁ, আমি বুঝতে পারি যে আমি এটি করতে পারি - বা আরও ভাল, সমস্ত মানগুলির মধ্যে পুনরাবৃত্তি না হয়ে বিপরীত অনুসন্ধানের জন্য একটি মানচিত্র ব্যবহার করুন। আমি আমার প্রশ্নে এটি উল্লেখ করেছি এবং আমি আরও উল্লেখ করেছি যে প্রতিটি এনামে বয়লারপ্লেট কোড এড়াতে আমি আরও ভাল সমাধানের সন্ধান করছি।
sleske

2

বিপরীত এনুমের একটি খুব পরিষ্কার ব্যবহারের উদাহরণ

পদক্ষেপ 1 একটি interfaceEnumConverter সংজ্ঞায়িত করুন

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

ধাপ ২

বিপরীতমুখী একটি শ্রেণীর নাম তৈরি করুন

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>অবশ্যই এবং ইন্টারফেস পদ্ধতির ওভাররাইডের পদ্ধতিগুলির সাথে। আপনার একটি স্ট্যাটিক রিভার্সইনাম্যাপ শুরু করতে হবে।

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
জাভাতে এনামরা সেভাবে আচরণ করে না। তারা একটি সুস্পষ্ট ধরনের।
ক্রিস থম্পসন

প্রতিটি এনাম অবজেক্টের একটি অভ্যন্তরীণ সংখ্যা থাকবে (নামটি যে অবস্থানে এটি ঘোষিত হয়েছিল), এবং এটি .ordinal()পদ্ধতি দ্বারা অ্যাক্সেস করা যেতে পারে । (অন্য উপায়ে, ব্যবহার করুন BonusType.values()[i]।) তবে উপরে উল্লিখিত উদাহরণে এখানে সূচীগুলি এবং বাইরের মানগুলি একত্রিত হয় না।
পাওলো ইবারম্যান

1

সত্যিই দুর্দান্ত প্রশ্ন :-) আমি মিঃ ফার্গুসন'র অনুরূপ সমাধানটি কিছুদিন আগে ব্যবহার করেছি। আমাদের দ্রবীভূত এনাম দেখতে দেখতে:

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()- স্ট্যাটিক সহায়ক পদ্ধতির দরকার নেই।
sleske

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

দেওয়া হলে

পাবলিক এনাম বোনাসটাইপ {মাসিক (0), বছর পূর্বে (1), ওএনফুফ (2)}

বোনাসটাইপ বোনাস = বছর বছর;

System.out.println (বোনাস.অর্ডিনাল () + ":" + বোনাস)

আউটপুট: 1: বছর বছর


0

আপনার যদি ক্লাস কার থাকে

public class Car {
    private Color externalColor;
}

এবং সম্পত্তি রঙ একটি শ্রেণি

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

এবং আপনি রঙ একটি এনাম রূপান্তর করতে চান

public class CarDTO {
    private ColorEnum externalColor;
}

কেবলমাত্র একটি পদ্ধতি যুক্ত করুন রঙ বর্গ রূপান্তর করতে রঙ মধ্যে ColorEnum

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

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

এবং ভিতরে কলারএনম getById () পদ্ধতি প্রয়োগ করে

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

এখন আপনি ক্লাসম্যাপ ব্যবহার করতে পারেন

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);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.