For example, I want to sort Enum. And I have an object with key as Enum
UPDATED
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;
}
}
Sorting Arrays.sort
uses TimSort
or MergeSort
to run on average O (n log n)
. But if we use a finite number of constants ( Enums
), we can use the counting sort in time O (n)
. Is there a standard mechanism for using counting sort for Enums
in java
?
If you know the order of the constants in advance you can use a HashMap
to implement a counting sort:
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);
}
The complexity of this approach is O(n)
in average.
In the updated version of the question, you are asking about pigeonhole sort . It is similar to counting sort but has its own name. We need several changes in the algorithm above. First, we need to replace a HashMap<MyEnum, Integer>
with HashMap<MyEnum, List<Bean>>
, and store all Bean
objects in the corresponding lists. Then after iteration through the input, we need to join all that lists in the specified order.
A distinct non answer here: don't.
Do not worry about O(n) vs O(n*log(n)). Worry about writing human readable code that can be maintained and enhanced over time.
There are two cases:
Long story short: this sounds like a typical pre-mature optimisation. And then the only valid answer is: focus on writing clean, elegant code that gets the job done. Then measure with real data. And then decide if further action is required (and most of times: it is not).
Ok, no discussing about should we use O(n)
or O(nlogn)
is enough. Anyway, probably you could implement custom counting sort
algorithm? (I do not remember that any lib I know have this):
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;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.