有幾個微妙的東西去在這。這不是Stack Overflow上其他地方常見的「破碎比較器」問題。雖然這個比較器確實壞了,但很難看到。
第一個問題是比較器主要負責比較Double
值,即盒裝double
的值。鑑於>
操作員將執行自動取消裝箱操作並對所包含的值進行數字比較,==
操作員將測試參考相等性。一般而言,
Double.valueOf(1.23) == Double.valueOf(1.23) // WARNING: reference comparison, not numeric!
將是false
。如果你真的想測試Double
值的數值相等,你必須做
if (o1.getValue().doubleValue() == o2.getValue.doubleValue()) ...
這主要是工作,如果您輸入只包含實際數值。不過,我懷疑你的輸入包含NaN
值,這些值具有模糊(甚至無意義)的行爲。特別是,將NaN
與任何數值比較都是錯誤的,並且NaN
比較不等於自身!這違反了關於數字比較的各種規則;事實上,NaN
就實數而言是無序的。這就是排序算法遇到NaN
值時中斷的原因。
(NaN
是除以0.0通過0.0,除其他事項外的結果。)
有一種方法Double.compare(double d1, double d2)
,處理NaN
合理;它將NaN
的值整理爲Double.POSITIVE_INFINITY
以上。 (這也區別於負零正零,但是這不太可能造成你的問題。)有一個伴隨方法Double.compareTo(Double)
相比之下盒裝Double
值。
我已經重寫你的比較是這樣的:
Collections.sort(res, new Comparator<Entry<Integer, Double>>() {
public int compare(Entry<Integer, Double> o1,
Entry<Integer, Double> o2) {
if (isDesc) {
return o2.getValue().compareTo(o1);
} else {
return o1.getValue().compareTo(o2);
}
}
}
由於Double
是Comparable
本身,在Java中8,你可以通過避免使用工具方法上Map.Entry
編寫自己的比較。您也可以使用List
的sort()
默認的方法,這將是在一般的速度更快:
if (isDesc) {
res.sort(Map.Entry.<Integer,Double>comparingByValue().reversed());
} else {
res.sort(Map.Entry.comparingByValue());
}
(不幸的是,類型推理完全不是那麼回事,所以你必須以獲得提供「型證人」 )
最後,您可以使用「菱形」運算符和ArrayList
拷貝構造函數更加簡潔地複製映射條目。重寫的程序是這樣的:
public static List<Entry<Integer, Double>> sortMap(
Map<Integer, Double> curMap, final boolean isDesc) {
List<Entry<Integer, Double>> res = new ArrayList<>(curMap.entrySet());
if (isDesc) {
res.sort(Map.Entry.<Integer,Double>comparingByValue().reversed());
} else {
res.sort(Map.Entry.comparingByValue());
}
return res;
}