我有下面的比較功能Comparator<Foo>
:我怎樣才能逃避不及時比較器?
float d = o1.bar - o2.bar;
if (Math.abs(d) <= 0.001) {
return 0;
} else {
return d < 0 ? -1 : 1; // inline Math.copySign
}
本質上講,這應該是比較基於他們bar
等兩項Foo
小號除非值足夠接近,在這種情況下,他們應該被宣佈相等。 (這很重要,因爲我在此之後做了另一個排序,在不同的屬性上。)
顯然,這不是一個傳遞式比較器。如果有Foo
小號f1
,f2
和f3
與作爲1.999
,2.000
和2.001
的bar
值,分別的話,按照我的比較,f1==f2
和f2==f3
但f1 != f3
。
調用sort(myListOfFoo, myFooComparator)
給出了「比較方法違反其總合約!」錯誤很少,但確定性。
如何在不產生此錯誤的情況下使用Collections.sort(List, Comparator)
這種比較器?
另外,有沒有什麼方法可以存儲我的數據,這將允許比較器正常工作?在施工時將每個浮動量調整到最接近的0.001
將是最簡單的解決方案,除了Foo.bar
字段實際上是基於任意距離度量計算的,所以並不那麼簡單。
實際的代碼是:
float d = metric.distance(vertex, o1)
- metric.distance(vertex, o2);
if (Math.abs(d) < threshold) {
return 0;
} else {
return d < 0 ? -1 : 1; // inline Math.copySign
}
其中o1
,o2
,和vertex
是class Point { float x; float y; }
和metric
實例是interface DistanceMetric { float distance(Point p1, Point p2); }
一個實例。值得注意的是,即使在標準的歐幾里德度量上,這也是失敗的。
您的解決方案也不適用。 Supose threshold = 0.5:2.1被舍入到2.0,2.4被舍入到2.5。按照你的規則,它們應該是平等的,但現在2.1比2.4小。同樣適用於小屋或地板。 – Cristopher
@Cristopher謝謝。這是真的,也是一個好點。但它不起作用的主要原因仍然是因爲這些值是不恆定的。 – wchargin
如果你只是想對'Point'進行排序,閾值的意義何在?你需要在相同的距離去除點,或類似的東西?因爲,否則,您可以使用基於距離的「正常」排序,並且「相同」距離處的所有點將被正確排序,並且將在排序列表中依次排列。 –