Сортировка массивов перечислений в Java
Имеется некое перечисление
enum MyEnum {
FOO, BAR, BAZ, QUX, ARG, ANT;
}
И массив/список из его значений (длиной больше чем "длина" перечисления MyEnum.values().length, но это неважно).
MyEnum[] vals = {MyEnum.BAR, MyEnum.BAZ, MyEnum.ARG, MyEnum.ANT, MyEnum.FOO, MyEnum.QUX, MyEnum.ANT, MyEnum.FOO};
Почему при сортировке этого массива при помощи стандартного метода Arrays.sort получается результат:
Arrays.sort(vals);
System.out.println(Arrays.toString(vals));
// [FOO, FOO, BAR, BAZ, QUX, ARG, ANT, ANT]
Как получить массив значений перечислений, отсортированный по алфавиту?
Ответы (1 шт):
Перечисления в Java представляют собой классы вида Enum<E extends Enum<E>>, которые в свою очередь реализуют интерфейс Comparable<E>, то есть перечисления поддерживают естественное упорядочивание (natural ordering) благодаря реализации метода Enum::int compareTo(E o).
В документации указывается, что естественный порядок, реализованный в данном методе -- это порядок, в котором были объявлены константы перечисления:
public final int compareTo(E o)
Compares this enum with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object. Enum constants are only comparable to other enum constants of the same enum type. The natural order implemented by this method is the order in which the constants are declared.
Фактически, для сравнения в естественном порядке используются значения ordinal (см. пример реализации в Open JDK 8)
Соответственно, для сортировки массива перечислений в алфавитном порядке достаточно передать в перегруженный метод Arrays::sort(T[] arr, Comparator<? super T> cmp) компаратор по полю/методу Enum::name():
Arrays.sort(vals, Comparator.comparing(MyEnum::name));
System.out.println(Arrays.toString(vals));
// [ANT, ANT, ARG, BAR, BAZ, FOO, FOO, QUX]
Аналогичный компаратор следует использовать и при сортировке списков List::sort(Comparator<? super E> cmp), потоков в Stream API Stream::sorted(Comparator<? super E> cmp) или для сортированных сетов / очередей приоритетов и т.п.