Java 如何通过计数排序对枚举进行排序?

Java 如何通过计数排序对枚举进行排序?,java,algorithm,sorting,enums,Java,Algorithm,Sorting,Enums,例如,我想对枚举进行排序。我有一个对象,其键为Enum 已更新 public class Main { public static void main(String[] args) throws Exception { Bean[] mass = new Bean[] { new Bean(new Object(), A), new Bean(new Object(), C), new Bean(new Object(), D), ne

例如,我想对枚举进行排序。我有一个对象,其键为
Enum

已更新

public class Main {

    public static void main(String[] args) throws Exception {

        Bean[] mass = new Bean[] { new Bean(new Object(), A), new Bean(new Object(), C), new Bean(new Object(), D),
                new Bean(new Object(), B), new Bean(new Object(), A) }; // 1, 3, 4, 2, 1
        Arrays.sort(mass, new EnumComparator());
        System.out.println(Arrays.toString(mass)); //[1, 1, 2, 3, 4]

    }
}

class EnumComparator implements Comparator<Bean> {

    @Override
    public int compare(Bean o1, Bean o2) {
        return o1.key.toString().compareTo(o2.key.toString());
    }

}

class Bean {
    public Object data;
    public Enum key;

    public Bean(Object data, Enum key) {
        super();
        this.data = data;
        this.key = key;
    }

    @Override
    public String toString() {
        return key.toString();
    }

}

enum MyEnum {

    D("4"),
    A("1"),
    B("2"),
    C("3");

    private String index;

    private MyEnum(String index) {
        this.index = index;
    }

    @Override
    public String toString() {
        return index;
    }

}
公共类主{
公共静态void main(字符串[]args)引发异常{
Bean[]mass=newbean[]{newbean(newobject(),A),newbean(newobject(),C),newbean(newobject(),D),
newbean(newobject(),B),newbean(newobject(),A)};//1,3,4,2,1
sort(mass,new enumparator());
System.out.println(Arrays.toString(mass));/[1,1,2,3,4]
}
}
类EnumComparator实现Comparator{
@凌驾
公共int比较(Bean o1,Bean o2){
返回o1.key.toString().compareTo(o2.key.toString());
}
}
类豆{
公共对象数据;
公共枚举密钥;
公共Bean(对象数据、枚举键){
超级();
这个数据=数据;
this.key=key;
}
@凌驾
公共字符串toString(){
return key.toString();
}
}
髓鞘{
D(“4”),
A(“1”),
B(“2”),
C(“3”);
私有字符串索引;
私有MyEnum(字符串索引){
这个指数=指数;
}
@凌驾
公共字符串toString(){
收益指数;
}
}

排序
数组。排序
使用
TimSort
MergeSort
平均运行
O(n log n)
。但是如果我们使用有限数量的常量(
enum
),我们可以使用in time
O(n)
。在
java
中是否有标准的机制来使用
enum
的计数排序?

如果您事先知道常量的顺序,您可以使用
HashMap
来实现计数排序:

List<MyEnum> countingSort(MyEnum order[], List<MyEnum> input) {
    HashMap<MyEnum, Integer> countMap = new HashMap<>();
    for (MyEnum obj : input) {
        countMap.put(obj, countMap.getOrDefault(obj, 0) + 1);
    }

    List<MyEnum> result = new ArrayList<>();
    for (MyEnum obj : order) {
        for (int i = 0; i < countMap.getOrDefault(obj, 0); ++i) {
            result.add(obj);
        }
    }

    return result;
}

public static void main (String[] args) {   
    MyEnum order[] = {A, B, C, D};
    List<MyEnum> input = Arrays.asList(D, C, A, B, D, D, B, A, A, C, D);
    List<MyEnum> res = countingSort(order, input);
} 
List countingSort(MyEnum顺序[],列表输入){
HashMap countMap=新HashMap();
用于(MyEnum对象:输入){
countMap.put(obj,countMap.getOrDefault(obj,0)+1);
}
列表结果=新建ArrayList();
对于(MyEnum obj:订单){
对于(int i=0;i
这种方法的复杂性平均为
O(n)


在问题的更新版本中,您正在询问。它类似于计数排序,但有自己的名称。我们需要对上面的算法进行一些修改。首先,我们需要用
HashMap
替换
HashMap
,并将所有
Bean
对象存储在相应的列表中。然后在通过输入进行迭代之后,我们需要按照指定的顺序连接所有列表

这里有一个明显的非答案:不要

不要担心O(n)和O(n*log(n))。担心编写可以随时间而维护和增强的可读代码

有两种情况:

  • n是如此之大以至于差异很重要。这意味着n可能是一个非常大的数。然后,你将面临一大堆其他更重要的问题,你应该首先关注这些问题。因为你的“处理链”中的每一步都很重要。在这种情况下,您必须仔细查看每个步骤,并确定如何对其进行优化(最有可能的是,您必须先进行测量,然后才能应用产生影响的优化)
  • n是如此之小以至于。。。uups:n很小。这意味着我们首先谈论的是“少于毫秒”

长话短说:这听起来像是典型的早熟优化。唯一有效的答案是:专注于编写干净、优雅的代码来完成任务。然后用真实数据进行测量。然后决定是否需要采取进一步的行动(大多数情况下:不需要)。

好的,我们不需要讨论应该使用
O(n)
还是
O(nlogn)
就足够了。不管怎样,也许您可以实现定制的
计数排序
算法?(我不记得我知道的任何图书馆都有这个):

private静态void countSort(Bean[]mass){
List[]arr=(List[])新列表[MyEnum.values().length];
for(Bean:mass){
int pos=Integer.parseInt(bean.key.getIndex())-1;
如果(arr[pos]==null)
arr[pos]=新的ArrayList();
arr[pos].add(bean);
}
int i=0;
for(列表bean:arr)
for(Bean:Bean)
质量[i++]=bean;
}

您总是可以使用其他实用程序方法,而不是
数组。sort()
或自己编写一个,但只需几个元素,这真的很重要吗?性能上的差异几乎可以忽略不计。这并不是说计数排序实际上更适合于枚举。我更愿意问一个问题,如果对于有限的枚举集,在
O(n)
O(n log n)
中排序会有什么不同。虽然与渐近分析无关,但常数对于运行代码来说可能非常有趣。我有一个对象数组,其中
Enum
作为键,我需要排序。Java中没有计算排序的标准机制,period。虽然这是一个相当琐碎的算法来写自己,你可能会在网上找到无数这样的例子。我不同意你。如果有一个对象使用Enum作为键,并且需要使用这些对象对数组进行排序,则需要记住相同对象的数量,并从必要的索引填充新数组,这并不是那么简单。是的,一切都是正确的。但在您的解决方案中,我们用相同的对象(而不是真实对象)填充列表)。假设一个复合对象包含一个
Enum
作为键字段,我们需要所有其余的信息。例如
objA{MyEnum Enum=MyEnum.a,public Integer index=**1**)
objB{MyEnum enu
private static void countSort(Bean[] mass) {
    List<Bean>[] arr = (List<Bean>[])new List[MyEnum.values().length];

    for (Bean bean : mass) {
        int pos = Integer.parseInt(bean.key.getIndex()) - 1;

        if (arr[pos] == null)
            arr[pos] = new ArrayList<>();

        arr[pos].add(bean);
    }

    int i = 0;

    for (List<Bean> beans : arr)
        for (Bean bean : beans)
            mass[i++] = bean;
}