enum ใน Java ใช้Comparable
อินเทอร์เฟซ ก็จะได้รับความสุขที่จะแทนที่Comparable
's compareTo
วิธี แต่ที่นี่ก็ทำเครื่องหมายเป็นครั้งสุดท้าย ลำดับธรรมชาติเริ่มต้นEnum
ของcompareTo
คือลำดับที่ระบุไว้
ไม่มีใครรู้ว่าทำไม Java enums ถึงมีข้อ จำกัด นี้?
enum ใน Java ใช้Comparable
อินเทอร์เฟซ ก็จะได้รับความสุขที่จะแทนที่Comparable
's compareTo
วิธี แต่ที่นี่ก็ทำเครื่องหมายเป็นครั้งสุดท้าย ลำดับธรรมชาติเริ่มต้นEnum
ของcompareTo
คือลำดับที่ระบุไว้
ไม่มีใครรู้ว่าทำไม Java enums ถึงมีข้อ จำกัด นี้?
คำตอบ:
เพื่อความมั่นคงผมคิดว่า ... เมื่อคุณเห็นenum
ชนิดที่คุณรู้สำหรับข้อเท็จจริงที่สั่งซื้อตามธรรมชาติของมันคือคำสั่งซื้อที่คงที่มีการประกาศ
ในการแก้ปัญหานี้คุณสามารถสร้างของคุณเองComparator<MyEnum>
และใช้งานได้อย่างง่ายดายเมื่อใดก็ตามที่คุณต้องการลำดับที่แตกต่างกัน:
enum MyEnum
{
DOG("woof"),
CAT("meow");
String sound;
MyEnum(String s) { sound = s; }
}
class MyEnumComparator implements Comparator<MyEnum>
{
public int compare(MyEnum o1, MyEnum o2)
{
return -o1.compareTo(o2); // this flips the order
return o1.sound.length() - o2.sound.length(); // this compares length
}
}
คุณสามารถใช้Comparator
โดยตรง:
MyEnumComparator c = new MyEnumComparator();
int order = c.compare(MyEnum.CAT, MyEnum.DOG);
หรือใช้ในคอลเลกชันหรืออาร์เรย์:
NavigableSet<MyEnum> set = new TreeSet<MyEnum>(c);
MyEnum[] array = MyEnum.values();
Arrays.sort(array, c);
ข้อมูลเพิ่มเติม:
MyEnumComparator
ไม่มีสถานะจึงควรเป็นซิงเกิลตันโดยเฉพาะอย่างยิ่งหากคุณกำลังทำสิ่งที่ @Bombe แนะนำ แต่คุณจะทำบางอย่างMyEnumComparator.INSTANCE.compare(enum1, enum2)
เพื่อหลีกเลี่ยงการสร้างวัตถุที่ไม่จำเป็น
LENGTH_COMPARATOR
ฟิลด์คงที่ใน enum ด้วยวิธีนี้จะเป็นเรื่องง่ายที่จะหาสำหรับทุกคนที่ใช้ enum
ให้การใช้งานค่าเริ่มต้นของ CompareTo ที่ใช้ลำดับซอร์สโค้ดนั้นใช้ได้ การทำให้สุดท้ายเป็นความผิดพลาดในส่วนของซัน ลำดับบัญชีสำหรับคำสั่งประกาศแล้ว ฉันยอมรับว่าในสถานการณ์ส่วนใหญ่นักพัฒนาสามารถจัดลำดับองค์ประกอบได้อย่างมีเหตุผล แต่บางครั้งก็ต้องการให้ซอร์สโค้ดจัดระเบียบในลักษณะที่ทำให้การอ่านง่ายและการบำรุงรักษาเป็นสิ่งสำคัญยิ่ง ตัวอย่างเช่น:
//===== SI BYTES (10^n) =====//
/** 1,000 bytes. */ KILOBYTE (false, true, 3, "kB"),
/** 106 bytes. */ MEGABYTE (false, true, 6, "MB"),
/** 109 bytes. */ GIGABYTE (false, true, 9, "GB"),
/** 1012 bytes. */ TERABYTE (false, true, 12, "TB"),
/** 1015 bytes. */ PETABYTE (false, true, 15, "PB"),
/** 1018 bytes. */ EXABYTE (false, true, 18, "EB"),
/** 1021 bytes. */ ZETTABYTE(false, true, 21, "ZB"),
/** 1024 bytes. */ YOTTABYTE(false, true, 24, "YB"),
//===== IEC BYTES (2^n) =====//
/** 1,024 bytes. */ KIBIBYTE(false, false, 10, "KiB"),
/** 220 bytes. */ MEBIBYTE(false, false, 20, "MiB"),
/** 230 bytes. */ GIBIBYTE(false, false, 30, "GiB"),
/** 240 bytes. */ TEBIBYTE(false, false, 40, "TiB"),
/** 250 bytes. */ PEBIBYTE(false, false, 50, "PiB"),
/** 260 bytes. */ EXBIBYTE(false, false, 60, "EiB"),
/** 270 bytes. */ ZEBIBYTE(false, false, 70, "ZiB"),
/** 280 bytes. */ YOBIBYTE(false, false, 80, "YiB");
การสั่งซื้อข้างต้นดูดีในซอร์สโค้ด แต่ไม่ใช่วิธีที่ผู้เขียนเชื่อว่าการเปรียบเทียบควรใช้งานได้ ลักษณะการทำงาน CompareTo ที่ต้องการคือการสั่งซื้อเป็นจำนวนไบต์ การจัดลำดับซอร์สโค้ดที่จะทำให้เกิดขึ้นจะทำให้องค์กรของโค้ดลดลง
ในฐานะลูกค้าของการแจงนับฉันไม่สนใจวิธีการจัดระเบียบซอร์สโค้ดของผู้เขียน ฉันต้องการให้อัลกอริทึมการเปรียบเทียบของพวกเขามีเหตุผลบางอย่าง Sun ใส่ตัวเขียนซอร์สโค้ดโดยไม่จำเป็น
ค่าการแจงนับจะเรียงลำดับอย่างแม่นยำตามลำดับที่ประกาศไว้ นี่เป็นส่วนหนึ่งของข้อกำหนดภาษา Java ดังนั้นจึงเป็นไปตามที่ค่าการแจงนับสามารถเปรียบเทียบได้ก็ต่อเมื่อเป็นสมาชิกของ Enum เดียวกัน ข้อกำหนดต้องการรับประกันเพิ่มเติมว่าลำดับการเทียบเคียงที่ส่งคืนโดย CompareTo () จะเหมือนกับลำดับที่ประกาศค่า นี่คือคำจำกัดความของการแจงนับ
หนึ่งคำอธิบายที่เป็นไปได้คือควรจะสอดคล้องกับcompareTo
equals
และequals
สำหรับ enums ควรสอดคล้องกับความเท่าเทียมกันของข้อมูลประจำตัว ( ==
)
หากcompareTo
ที่ใดไม่เป็นที่สิ้นสุดจะเป็นไปได้ที่จะแทนที่ด้วยพฤติกรรมที่ไม่สอดคล้องกับequals
ซึ่งจะเป็นการตอบโต้ที่ใช้งานง่ายมาก
หากคุณต้องการเปลี่ยนลำดับตามธรรมชาติขององค์ประกอบของ enum ให้เปลี่ยนลำดับในซอร์สโค้ด