[英]Sorting: How to create a particular custom order, then alphabetic sort in java
我有一個大約70個領域的Enum。
我希望其中10個以特定順序顯示,然后我希望其余部分使用比較器按字母順序顯示。 我嘗試了很多東西,但我無法讓它發揮作用。
這是一個具有簡化屬性的枚舉示例我希望首先顯示Picard,Worf和William,然后按字母順序顯示其余部分
我不能使用任何第三個庫。 它必須是java核心。 所以如果你想提供番石榴答案,或者apache commons的答案,除了java核心之外,請這樣做。
public enum StarTrek {
JeanLucPicard("Picard"),
GeordiLaForge("Geordi"),
DiannaTroi("Dianna"),
Worf("Worf"),
WilliamRiker("William"),
Q("Q");
private String label;
StarTrek(String label) { this.label = label; }
@Override public String toString() { return label; }
}
List<StarTrek> specificOrder = Arrays.asList(StarTrek.JeanLucPicard, StarTrek.Worf, StarTrek.WilliamRiker);
Comparator<StarTrek> comp = new Comparator<StarTrek>() {
@Override
public int compare(StarTrek o1, StarTrek o2) {
//TODO: loop through the specific order, and display those first, then for the rest, go alphabetic
return 0;
}
};
List<StarTrek> all = Arrays.asList(StarTrek.values());
Collections.sort(all, comp);
為了按特定順序顯示,在枚舉中放置其他數據是不好的設計。 相反,將所有邏輯放在Comparator
,如下所示:
public class StarTrekSorter implements Comparator<StarTrek> {
private static final List<StarTrek> ORDERED_ENTRIES = Arrays.asList(
StarTrek.JeanLucPicard, StarTrek.Worf, StarTrek.WilliamRiker);
@Override
public int compare(StarTrek o1, StarTrek o2) {
if (ORDERED_ENTRIES.contains(o1) && ORDERED_ENTRIES.contains(o2)) {
// Both objects are in our ordered list. Compare them by
// their position in the list
return ORDERED_ENTRIES.indexOf(o1) - ORDERED_ENTRIES.indexOf(o2);
}
if (ORDERED_ENTRIES.contains(o1)) {
// o1 is in the ordered list, but o2 isn't. o1 is smaller (i.e. first)
return -1;
}
if (ORDERED_ENTRIES.contains(o2)) {
// o2 is in the ordered list, but o1 isn't. o2 is smaller (i.e. first)
return 1;
}
return o1.toString().compareTo(o2.toString());
}
}
現在,你可以排序:
public static void main(String[] args) {
List<StarTrek> cast = Arrays.asList(StarTrek.values());
Collections.sort(cast, new StarTrekSorter());
for (StarTrek trek : cast) {
System.out.println(trek);
}
}
打印
Picard
Worf
William
Dianna
Geordi
Q
我會這樣做:
JeanLucPicard("Picard", 0),
GeordiLaForge("Geordi"),
DiannaTroi("Dianna"),
Worf("Worf", 1),
WilliamRiker("William", 2),
Q("Q");
StarTrek(String label) { this(label, -1); }
StarTrek(String label, int orderHint) { this.label=label; this.orderHint=orderHint; }
在compare
方法中,這樣的事情:
if (orderHint == -1) {
return o1.label.compareTo(o2.label));
}
return o2.orderHint-o1.orderHint;
在列表中首先列出您想要特殊訂購的枚舉,然后使用以下代碼:
Comparator<StarTrek> comp = new Comparator<StarTrek>() {
public int compare(StarTrek o1, StarTrek o2) {
if (o1.ordinal() < 3)
return o2.ordinal() < 3 ? o1.ordinal() - o2.ordinal() : 1;
return o2.ordinal() < 3 ? -1 : o1.name().compareTo(o2.name());
}
};
您可以在枚舉中定義一個額外的構造函數,它接受一個索引參數,然后為您想要的實例提供索引(保留您想要按字母順序排列的索引):
enum StarTrek {
JeanLucPicard("Picard"),
GeordiLaForge("Geordi"),
DiannaTroi("Dianna"),
Worf("Worf", 2),
WilliamRiker("William", 1),
Q("Q");
private final String label;
private final Integer index;
StarTrek(final String label, final Integer index ) { this.label = label; this.index = index; }
StarTrek(final String label) { this.label = label; this.index = Integer.MAX_VALUE; }
@Override public String toString() { return label; }
public Integer getIndex() {
return index;
}
}
然后你的比較器必須看起來像:
final Comparator<StarTrek> comp = new Comparator<StarTrek>() {
@Override
public int compare(final StarTrek o1, final StarTrek o2) {
if (!o1.getIndex().equals(o2.getIndex())) {
return o1.getIndex().compareTo(o2.getIndex());
}
return o1.toString().compareTo(o2.toString());
}
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.