Wyliczenie w Javie implementuje Comparable
interfejs. Byłoby miło, aby zastąpić Comparable
„s compareTo
metody, ale tutaj jest oznaczony jako wersja ostateczna. Domyślną naturalny porządek na Enum
„s compareTo
jest podana kolejność.
Czy ktoś wie, dlaczego wyliczenia Java mają to ograniczenie?
java
enums
comparable
compareto
neu242
źródło
źródło
Odpowiedzi:
Myślę, że dla spójności ... kiedy widzisz
enum
typ, wiesz na pewno , że jego naturalny porządek to kolejność, w której deklarowane są stałe.Aby obejść ten problem, możesz łatwo utworzyć własną
Comparator<MyEnum>
i używać jej, gdy potrzebujesz innej kolejności: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 } }
Możesz skorzystać
Comparator
bezpośrednio z:MyEnumComparator c = new MyEnumComparator(); int order = c.compare(MyEnum.CAT, MyEnum.DOG);
lub użyj go w kolekcjach lub tablicach:
NavigableSet<MyEnum> set = new TreeSet<MyEnum>(c); MyEnum[] array = MyEnum.values(); Arrays.sort(array, c);
Dalsza informacja:
źródło
MyEnumComparator
nie ma stanu, powinien to być po prostu singleton, zwłaszcza jeśli robisz to, co sugeruje @Bombe; zamiast tego zrobiłbyś coś takiego, jakMyEnumComparator.INSTANCE.compare(enum1, enum2)
uniknięcie niepotrzebnego tworzenia obiektówLENGTH_COMPARATOR
statycznym polu w wyliczeniu. W ten sposób łatwo byłoby go znaleźć dla każdego, kto używa wyliczenia.Podanie domyślnej implementacji compareTo, która używa kolejności kodu źródłowego, jest w porządku; uczynienie go ostatecznym było błędem ze strony Sun. Porządek porządkowy już uwzględnia kolejność deklaracji. Zgadzam się, że w większości sytuacji programista może po prostu logicznie uporządkować swoje elementy, ale czasami chce się, aby kod źródłowy był zorganizowany w sposób, który sprawia, że czytelność i konserwacja są najważniejsze. Na przykład:
//===== 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");
Powyższa kolejność wygląda dobrze w kodzie źródłowym, ale autor uważa, że nie tak powinno działać funkcja compareTo. Żądanym zachowaniem compareTo jest uporządkowanie według liczby bajtów. Porządkowanie kodu źródłowego, które by to spowodowało, degraduje organizację kodu.
Jako klient wyliczenia nie obchodziło mnie, jak autor zorganizował swój kod źródłowy. Chciałbym jednak, żeby ich algorytm porównawczy miał jakiś sens. Firma Sun niepotrzebnie związała twórców kodu źródłowego.
źródło
Wartości wyliczeń są precyzyjnie uporządkowane logicznie zgodnie z kolejnością, w jakiej są zadeklarowane. Jest to część specyfikacji języka Java. W związku z tym wynika, że wartości wyliczenia można porównać tylko wtedy, gdy są członkami tego samego Enum. Specyfikacja chce dodatkowo zagwarantować, że porównywalna kolejność zwrócona przez funkcję compareTo () jest taka sama, jak kolejność, w której zadeklarowano wartości. To jest właśnie definicja wyliczenia.
źródło
Jednym z możliwych wyjaśnień jest to, że
compareTo
powinno być zgodne zequals
.A
equals
wyliczenia powinny być zgodne z równością tożsamości (==
).Gdyby
compareTo
nie było ostateczne, można by zastąpić to zachowaniem, które nie było zgodne zequals
, co byłoby bardzo sprzeczne z intuicją.źródło
Jeśli chcesz zmienić naturalną kolejność elementów wyliczenia, zmień ich kolejność w kodzie źródłowym.
źródło