[英]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 的概念:
出於性能原因,您可以存儲計算出的描述。
因為枚舉不能繼承,代碼重用必須在枚舉類之外。 讓我舉一個我們將在我們的項目中使用的例子:
現在代碼示例...
/** 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.