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 () จะเหมือนกับลำดับที่ประกาศค่า นี่คือคำจำกัดความของการแจงนับ
หนึ่งคำอธิบายที่เป็นไปได้คือควรจะสอดคล้องกับcompareToequals
และequalsสำหรับ enums ควรสอดคล้องกับความเท่าเทียมกันของข้อมูลประจำตัว ( ==)
หากcompareToที่ใดไม่เป็นที่สิ้นสุดจะเป็นไปได้ที่จะแทนที่ด้วยพฤติกรรมที่ไม่สอดคล้องกับequalsซึ่งจะเป็นการตอบโต้ที่ใช้งานง่ายมาก
หากคุณต้องการเปลี่ยนลำดับตามธรรมชาติขององค์ประกอบของ enum ให้เปลี่ยนลำดับในซอร์สโค้ด