Java实现Comparable接口排序极小差值数值时触发异常的优化方案咨询
现有实现的不合理之处
- 原始报错的根本原因:你直接对两个
double类型的距离差值做int强转,当两个距离的差值绝对值小于1时,不管差值是正还是负,强转后都会得到0,直接导致比较逻辑违反Comparable的传递性契约:比如A比B大0.3,B比C大0.4,A比C大0.7,此时compare(A,B)、compare(B,C)都返回0,但compare(A,C)返回1,完全不符合比较器的规则,所以排序时会抛出契约违反异常。 - 你目前的乘大系数方案仍然存在缺陷:
- 代码本身存在语法错误,两个乘完的值之间漏了减号,且方法参数类型
Eq和你类实现的Comparable<Coordinate>不匹配 - 逻辑上仍然有漏洞:如果两个距离的差值小于
1e-15,乘完1e15之后差值还是小于1,还是会出现强转为0的问题 - 极容易出现浮点精度溢出:过大的乘数可能导致距离值超出
double的精度范围,甚至溢出为无穷大,反而出现更不可控的比较错误
- 代码本身存在语法错误,两个乘完的值之间漏了减号,且方法参数类型
更优雅的解决方案
直接用JDK内置的Double.compare方法处理浮点比较即可,JDK已经封装好了所有浮点比较的边界处理逻辑,完全符合比较器契约:
@Override public int compareTo(Coordinate compared) { // 空判断可以根据自己的业务需求加 return Double.compare(this.distanceCenter, compared.getDistanceFromCenter()); }
如果是Java 8及以上版本,还可以不用修改Coordinate类的Comparable实现,排序时直接传入对应的比较器即可,扩展性更强:
// 直接对列表做排序,不需要Coordinate实现Comparable接口 coordinateList.sort(Comparator.comparingDouble(Coordinate::getDistanceFromCenter));
内容的提问来源于stack exchange,提问作者ale666
相关产品推荐
相关产品推荐

