例如,我想对Enum进行排序。我有一个密钥为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;
}
}
排序Arrays.sort
使用TimSort
或MergeSort
平均O (n log n)
投放。但是如果我们使用有限数量的常量(Enums
),我们可以及时使用counting sort O (n)
。是否有一种标准机制可以对Enums
中的java
使用计数排序?
答案 0 :(得分:1)
如果您事先知道常量的顺序,可以使用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);
}
这种方法的复杂性平均为O(n)
。
在问题的更新版本中,您询问pigeonhole sort。它类似于计数排序,但有自己的名称。我们需要在上面的算法中进行一些更改。首先,我们需要将HashMap<MyEnum, Integer>
替换为HashMap<MyEnum, List<Bean>>
,并将所有Bean
个对象存储在相应的列表中。然后在迭代输入之后,我们需要以指定的顺序连接所有列表。
答案 1 :(得分:0)
这里有一个独特的非答案:不要。
不要担心O(n)vs O(n * log(n))。担心编写可随时间维护和增强的人类可读代码。
有两种情况:
长话短说:这听起来像是典型的早熟优化。然后唯一有效的答案是:专注于编写干净,优雅的代码来完成工作。然后用实际数据测量。然后决定是否需要采取进一步行动(而且大部分时间:不是)。
答案 2 :(得分:0)
好的,没有讨论我们应该使用O(n)
还是O(nlogn)
就足够了。无论如何,可能你可以实现自定义counting sort
算法? (我不记得我认识的任何文库都有这个):
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;
}