簡體   English   中英

如何在 Java 中按字母順序對枚舉成員進行排序?

[英]How do I sort enum members alphabetically in Java?

我有一個枚舉類,如下所示:

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;
    }
}

后來在我的代碼中,我基本上遍歷 Letter 枚舉並將其成員打印到控制台:

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

我認為值()方法會給我的枚舉的有序視圖(如提到這里),但這里不是這種情況。 我只是按照我在 Letter 枚舉類中創建它們的順序獲取枚舉成員。 有沒有辦法按字母順序輸出枚舉的值? 我需要一個單獨的比較器對象,還是有內置的方法來做到這一點? 基本上,我希望根據 getDescription() 文本按字母順序對值進行排序:

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

或者只是重新排序聲明:-)

編輯:正如 KLE 所指出的,這假設描述在枚舉中是唯一的。

我認為 values() 方法會給我一個枚舉的有序視圖(如此處提到的),但這里的情況並非如此。 我只是按照我在 Letter 枚舉類中創建它們的順序獲取枚舉成員。

確切地說,聲明的順序對於枚舉來說很重要,所以我們很高興它們是按照這個順序返回的。 例如,當int i表示枚舉值時,執行values()[i]是一種非常簡單有效的查找枚舉實例的方法。 相反, ordinal()方法返回枚舉實例的索引。

有沒有辦法按字母順序輸出枚舉的值? 我需要一個單獨的比較器對象,還是有內置的方法來做到這一點? 基本上,我希望根據 getDescription() 文本按字母順序對值進行排序:

您所說的通常不是為枚舉定義的。 在這里,在您的上下文中,您的意思是getDescription()的結果。

正如您所說,您可以為這些描述創建一個 Comparator 那將是完美的:-)


請注意,通常,您可能需要為這些實例提供多個訂單

  • 聲明令(這是官方命令)
  • 描述順序
  • 其他人根據需要

你也可以稍微推動一下 DescriptionComparator 的概念:

  1. 出於性能原因,您可以存儲計算出的描述。

  2. 因為枚舉不能繼承,代碼重用必須在枚舉類之外。 讓我舉一個我們將在我們的項目中使用的例子:

現在代碼示例...

/** 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中的通用代碼不僅適用於一個枚舉類,還適用於項目中實現了Described interface 的任何枚舉類

如前所述,將代碼放在枚舉之外(否則將屬於它的地方)的重點是重用代碼。 兩個枚舉沒什么大不了的,但是我們的項目中有超過一千個枚舉,其中許多具有相同的接口......!

只需使用 Arrays.sort 和您自己的比較器對它們進行排序。

這是對任何類執行此操作的通用方法,而無需在您正在排序的類上實現 Comparable 或創建自定義比較器。 我發現我不想覆蓋 compareTo 的實例,因為它用於不同的目的,無論如何你不能用於枚舉,並且不斷創建包裝類是一種痛苦。 您可以傳入一個函數,該函數輸出您想用於排序目的的 Comparable 對象。

toComparable 函數僅對列表中的每個元素調用一次(對於自定義比較器而言並非如此),因此如果該調用對於某些類來說很昂貴,則特別好。 空值在內部處理,因此它比自定義比較器更易於使用。 一次調用 Java 7 的 TimSort 算法比對 SortedMap(紅黑樹或其他平衡樹實現)執行一堆 O(log N) 插入要高效得多。 而且您不受任何特定類或接口的限制。

在許多情況下,現實世界的性能提升是顯着的。 例如,在大小為 100k 的列表上使用 toString() 對 Doubles 進行排序時,性能提升大約是使用比較器的 5 倍。

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);
       }
    }
}

您可以在java8中使用帶有比較器的排序函數

enumlist.stream()
.sorted(Comparator.comparing(Enum::toString)).collect(Collectors.toList());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM