简体   繁体   English

排序:如何创建特定的自定义顺序,然后在java中进行字母排序

[英]Sorting: How to create a particular custom order, then alphabetic sort in java

I have an Enum with around 70 fields. 我有一个大约70个领域的Enum。

I want 10 of them to be displayed in a particular order, then I want the rest to be displayed alphabetically using a Comparator. 我希望其中10个以特定顺序显示,然后我希望其余部分使用比较器按字母顺序显示。 I have tried many things, but I can't get it to work. 我尝试了很多东西,但我无法让它发挥作用。

Here is a sample enum with reduces attributes I want Picard, Worf and William to display first, then the rest alphabetically 这是一个具有简化属性的枚举示例我希望首先显示Picard,Worf和William,然后按字母顺序显示其余部分

I cannot use any third libraries. 我不能使用任何第三个库。 It must be java core. 它必须是java核心。 So if you want to provide guava answers, or apache commons answer, please do so in addition to java core. 所以如果你想提供番石榴答案,或者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);

It is bad design to place additional data in your enum just for the purposes of displaying in a particular order. 为了按特定顺序显示,在枚举中放置其他数据是不好的设计。 Instead, place all that logic in your Comparator , as shown below: 相反,将所有逻辑放在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());
  }
}

Now, you can just sort: 现在,你可以排序:

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

which prints 打印

Picard
Worf
William
Dianna
Geordi
Q

I would do it like this: 我会这样做:

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

And in the compare method something like this: compare方法中,这样的事情:

if (orderHint == -1) {
   return o1.label.compareTo(o2.label));
}
return o2.orderHint-o1.orderHint;

List the enums you want special ordering for first in your list, then use this code: 在列表中首先列出您想要特殊订购的枚举,然后使用以下代码:

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

You could define an additional constructor in your enum, that takes an index parameter, then provide indexes for the instances you want to go first (leave the ones you want to go in alphabetical order unindexed): 您可以在枚举中定义一个额外的构造函数,它接受一个索引参数,然后为您想要的实例提供索引(保留您想要按字母顺序排列的索引):

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

Then your comparator would have to look like: 然后你的比较器必须看起来像:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM