如果您使用的是Java 6或下面你可以切換到Java 7,Java 7中得到加速,他們改變了排序算法TimSort執行在某些情況下更好(特別是它works well with partially sorted input) 。 Java 6及以下版本used MergeSort。
但是讓我們假設你使用的是Java 6.我試過三個版本:
Collections.sort():重複你所提供的比較器的運行我的機器上大約需要3.0秒 (包括讀取1,000,000個隨機生成的小寫ascii字符串的輸入)。
基數排序:建議其他答案Radix sort。我嘗試下面的代碼(假定的字符串均相同的長度,並且只有小寫ASCII):
String [] A = list.toArray(new String[0]);
for(int i = stringLength - 1; i >=0; i--) {
int[] buckets = new int[26];
int[] starts = new int[26];
for (int k = 0 ; k < A.length;k++) {
buckets[A[k].charAt(i) - 'a']++;
}
for(int k = 1; k < buckets.length;k++) {
starts[k] = buckets[k -1] + starts[k-1];
}
String [] temp = new String[A.length];
for(int k = 0; k < A.length; k++) {
temp[starts[A[k].charAt(i) - 'a']] = A[k];
starts[A[k].charAt(i) - 'a']++;
}
A = temp;
}
大約需要29.0秒到我的機器上完成。我不認爲這是爲這個問題實現基數排序的最好方式 - 例如,如果您進行了最重要的數字排序,那麼您可以儘早終止唯一的前綴。而且在使用原地排序方面也會有一些好處(有一個關於此的好消息 - 「The troubles with radix sort are in implementation, not in conception」)。我想寫一個更好的基於基數的解決方案來做到這一點 - 如果我有時間,我會更新我的答案。
存儲分類排序:我還實施了Peter Lawrey的bucket sort解決方案的稍微修改版本。下面的代碼:
Map<Integer, List<String>> buckets = new TreeMap<Integer,List<String>>();
for(String s : l) {
int key = s.charAt(0) * 256 + s.charAt(1);
List<String> list = buckets.get(key);
if(list == null) buckets.put(key, list = new ArrayList<String>());
list.add(s);
}
l.clear();
for(List<String> list: buckets.values()) {
Collections.sort(list);
l.addAll(list);
}
大約需要2.5秒完成我的機器上。我相信這個勝利來自於分區。
所以,如果切換到Java 7的TimSort不幫你,那麼我建議分區中的數據(使用類似bucket sort)。如果你需要更好的性能,那麼你也可以多線程處理分區。
實施快速排序並在列表中使用它。 – 2011-12-25 13:15:25
爲什麼不使用'SortedSet'?除非你有重複? – fge 2011-12-25 13:16:18
不確定它對速度有影響,但你的比較器是不正確的:如果你有s1 == null,s3 ==「a」和s4 ==「b」,你將有s1 == s3,s1 == s4,但是s3!= s4。確定零值是在非零值之前還是之後,但如果其中一個爲空,則不要使兩個字符串相等。 – 2011-12-25 13:21:25