Как сортировать члены перечисления в алфавитном порядке в Java?

у меня есть класс enum следующим образом:

public enum Letter {
    OMEGA_LETTER("Omega"), 
    GAMMA_LETTER("Gamma"), 
    BETA_LETTER("Beta"), 
    ALPHA_LETTER("Alpha"), 

    private final String description;

    Letter() {
      description = toString();
    }

    Letter(String description) {
      this.description = description;
    }

    public String getDescription() {
      return description;
    }
}

позже мой код я в основном повторяю над буквенным перечислением и распечатываю его члены на консоли:

for (Letter letter : Letter.values()) {
System.out.println(letter.getDescription());
}

Я думал, что метод values () даст мне упорядоченное представление перечисления (как упоминалось здесь), но здесь это не так. Я просто получаю члены перечисления в том порядке, в котором я их создал в классе letter enum. Есть ли способ вывести значения перечисления в в алфавитном порядке? Нужен ли мне отдельный объект компаратора, или есть встроенный способ сделать это? В основном я хотел бы, чтобы значения были отсортированы по алфавиту на основе текста getDescription ():

Alpha
Beta
Gamma
Omega

4 ответов


SortedMap<String, Letter> map = new TreeMap<String, Letter>();
for (Letter l : Letter.values()) {
    map.put(l.getDescription, l);
}
return map.values();

или просто переупорядочить деклараций :-)

Edit: как указал KLE, это предполагает, что описания уникальны в перечислении.


Я думал, что метод values () даст мне упорядоченное представление перечисления (как упоминалось здесь), но здесь это не так. Я просто получаю члены перечисления в том порядке, в котором я их создал в классе letter enum.

точно, порядок объявления считается значительным для перечислений, поэтому мы рады, что они возвращаются именно в этом порядке. Например, когда int i представляет значения перечисления, делаю values()[i] очень просто и эффективный способ найти экземпляр enum. Идти против-мудрый,ordinal() метод возвращает индекс экземпляр enum.

есть ли способ вывести значения перечисления в алфавитном порядке? Нужен ли мне отдельный объект компаратора, или есть встроенный способ сделать это? В основном я хотел бы, чтобы значения были отсортированы по алфавиту на основе текста getDescription ():

то, что вы называете стоимостью не является чем-то определенным для перечислений в общем. Здесь, в вашем контексте, Вы имеете в виду результат getDescription().

как вы говорите, вы могли бы создайте компаратор для этих описаний. Это было бы идеально :-)


обратите внимание, что в целом,вам может понадобиться несколько заказов на эти случаи:

  • порядок объявления (это официальный порядок)
  • описание порядка!--32-->
  • другим, как нужно

вы также можете немного подтолкнуть это понятие DescriptionComparator:

  1. по соображениям производительности вы можете сохранить вычисленные описания.

  2. поскольку перечисления не могут наследовать, повторное использование кода должно быть вне класса enum. Позвольте мне привести пример, который мы будем использовать в наших проектах:

теперь примеры кода...

/** Interface for enums that have a description. */
public interface Described {
  /** Returns the description. */
  String getDescription();
}

public enum Letter implements Described {
  // .... implementation as in the original post, 
  // as the method is already implemented
}

public enum Other implements Described {
  // .... same
}

/** Utilities for enums. */
public abstract class EnumUtils {

  /** Reusable Comparator instance for Described objects. */
  public static Comparator<Described> DESCRIPTION_COMPARATOR = 
    new Comparator<Described>() {
      public int compareTo(Described a, Described b) {
        return a.getDescription().compareTo(b.getDescription);
      }
    };

  /** Return the sorted descriptions for the enum. */
  public static <E extends Enum & Described> List<String> 
    getSortedDescriptions(Class<E> enumClass) {
      List<String> descriptions = new ArrayList<String>();
      for(E e : enumClass.getEnumConstants()) {
        result.add(e.getDescription());
      }
      Collections.sort(descriptions);
      return descriptions;
  }
}

// caller code
List<String> letters = EnumUtils.getSortedDescriptions(Letter.class);
List<String> others = EnumUtils.getSortedDescriptions(Other.class);

обратите внимание, что общий код в EnumUtils работает не только для одного класса enum, но работает для любого класса перечисления в вашем проекте, который реализует Described интерфейс.

как уже говорилось ранее, смысл наличия кода вне перечислений (где он иначе принадлежал бы) заключается в повторном использовании кода. Это не имеет большого значения для двух перечислений, но у нас есть более тысячи перечислений в нашем проекте, многие из них с одинаковыми интерфейсами...!


просто отсортируйте их с помощью массивов.сортировка и собственный компаратор.


вот общий способ сделать это с любым классом без необходимости реализации Comparable в классе, который вы сортируете или создаете пользовательский компаратор. Я нашел случаи, когда я не хочу переопределять compareTo, потому что он служит другой цели, вы не можете для перечислений в любом случае, и постоянное создание классов обертки-это боль. Вы можете передать функцию, которая выводит сопоставимый объект,который вы хотите использовать для сортировки.

функция toComparable вызывается только один раз для каждого элемента в списке (не так для пользовательского компаратора), поэтому особенно хорошо, если этот вызов дорог для некоторого класса. Значения Null обрабатываются внутри, поэтому их проще использовать, чем пользовательский компаратор. Один вызов алгоритма TimSort Java 7 значительно эффективнее, чем выполнение группы O(log N) вставок в SortedMap (красно-черное дерево или другую сбалансированную реализацию дерева). И вы не ограничены каким-либо конкретным классом или интерфейсом.

представление реального мира увеличение во многих случаях является значительным. Например, увеличение производительности примерно в 5 раз быстрее, чем при использовании компаратора при сортировке двойников с помощью toString () в списке размером 100k.

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;

public class GenericLetterSorter {
    public enum Letter {
        OMEGA_LETTER("Omega"), 
        GAMMA_LETTER("Gamma"), 
        BETA_LETTER("Beta"), 
        ALPHA_LETTER("Alpha"); 

        private final String description;

        Letter() {
          description = toString();
        }

        Letter(String description) {
          this.description = description;
        }

        public String getDescription() {
          return description;
        }
    }

public static void main(String[] args) {
    List<Letter> list = new ArrayList<>(Arrays.asList(Letter.values()));

    sort(list, new ToComparable<Letter>() {
        @Override
        public Comparable toComparable(Letter letter) {
            // sort based on the letter's description
            return letter == null ? null : letter.getDescription();
        }
    });

    for (Letter letter : list)
        System.out.println(letter == null ? null : letter.name());
}

    public interface ToComparable<T, C extends Comparable<? super C>> {
         C toComparable(T t);
    }

    public static <T, C extends Comparable<? super C>> void sort(List<T> list, ToComparable<T, C> function) {
       class Pair implements Comparable<Pair> {
          final T original;
          final C comparable;

          Pair(T original, C comparable) {
             this.original = original;
             this.comparable = comparable;
          }

          @Override
          public int compareTo(Pair other) {
                return
                  comparable == null && other.comparable == null ? 0 :
                  comparable == null ? -1 :
                  other.comparable == null ? 1 :
                  comparable.compareTo(other.comparable);
          }
       }

       List<Pair> pairs = new ArrayList<>(list.size());
       for (T original : list)
          pairs.add(new Pair(original, function.toComparable(original)));

       Collections.sort(pairs);

       ListIterator<T> iter = list.listIterator();
       for (Pair pair : pairs) {
          iter.next();
          iter.set(pair.original);
       }
    }
}