2013-02-26 77 views
4

我有一个约70个字段的Enum。排序:如何创建特定的自定义订单,然后按字母顺序排序java

我希望其中的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); 
+1

为什么不这样做的两个步骤? – 2013-02-26 14:36:47

+0

我已经通过不使用排序来解决它,只是删除和添加集合,但我想用排序来解决它。它更好。我也只想打电话给排序 – 2013-02-26 14:40:54

+0

我不太确定它更好。两个步骤对我来说会更具可读性,并阻止您使用仅用于显示的元数据污染您的枚举类。 – 2013-02-26 14:44:09

回答

16

它是坏的设计将额外的数据放在您的枚举中,仅用于以特定顺序显示的目的。取而代之的是,将所有的逻辑在你的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 
+4

+1我喜欢这个回答。你对设计问题是正确的。 – Kai 2013-02-26 15:02:59

+0

请你一步一步解释发生了什么事?它很难理解这个比较器 – 2013-02-26 15:16:40

+0

@Shervin我已经添加了一些评论来尝试和帮助。 “比较”方法总是很难把你的头围绕。 – 2013-02-26 20:24:41

2

我会做这样的:

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; 
+0

除了更改枚举实现之外,没有其他方法吗? – 2013-02-26 14:51:05

+0

@Shervin,是的,检查[我的答案](http://stackoverflow.com/a/15092169/474189)。 – 2013-02-26 14:55:22

0

你可以定义你的枚举额外的构造函数,它接受一个索引参数,然后为您想要首先执行的实例提供索引(将未按索引顺序排列的字母顺序排列):

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

名单要在列表中第一个特别定制的枚举,然后使用此代码:

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()); 
    } 
}; 
相关问题