前言

上周线上的一段排序的java代码出现了一个Comparison method violates its general contract,在解决这个问题的途中学到了一些知识这里总结分享一下。
异常原因
这个排序导致的异常将会在java7以上的版本出现,所以如果你的JDK从6升级到了7或者8,那一定要小心此异常。
在java7的兼容列表中,就有对此排序不兼容的说明:
Area: API: Utilities Synopsis: Updated sort behavior for Arrays and Collections may throw an IllegalArgumentException Description: The sorting algorithm used by java.util.Arrays.sort and (indirectly) by java.util.Collections.sort has been replaced. The new sort implementation may throw an IllegalArgumentException if it detects a Comparable that violates the Comparable contract. The previous implementation silently ignored such a situation. If the previous behavior is desired, you can use the new system property, java.util.Arrays.useLegacyMergeSort, to restore previous mergesort behavior. Nature of Incompatibility: behavioral RFE: 6804124
我从资料中查阅到java7开始引入了Timsort的排序算法。我之前一直以为大部分标准库的内置排序算法都是快速排序。现在才得知很多语言内部都使用Timsort排序。随后我在wiki百科上找到了这样一句话:
t was implemented by Tim Peters in 2002 for use in the Python programming language.
所以这个排序自然是以他命名的。
随后我又在网上找到了这样一张图排序比较的图:
可以发现,Timsort在表现上比QuickSort还要好。
这篇博客不去详细讨论Timsort的实现(看上去这个算法还挺复杂的),我可能会写另一篇博客单独讨论Timsort,简单来说Timsort结合了归并排序和插入排序。这个算法在实现过程中明确需要:严格的单调递增或者递减来保证算法的稳定性。
sgn(compare(x, y)) == -sgn(compare(y, x))((compare(x, y)>0) && (compare(y, z)>0)) implies compare(x, z)>0compare(x, y)==0 implies that sgn(compare(x, z))==sgn(compare(y, z)) for all z看上去很像离散数学课中学习的集合的对称性,传递性的关系。
所以异常的原因是因为排序算法不够严谨导致的,实际上业务上的代码经常不如纯技术上的严谨。比如对于这样一个算法:
选出航班中的最低价
那如果两个相等低价同时存在,按照寻找最低价的逻辑如果这么写:
if (thisPrice < lowPrice){
lowPrice = thisPrice;
}
那低价这个位置就是“先到先得”了。
但如果这么实现:
if(thisPrice <= lowPrice){
lowPrice = thisPrice;
}
那后面的低价就会覆盖前面的,变成了“后来者居上”。编程中经常遇到先到先得和后来者居上这两个问题。
所以对于上面那个需要提供严谨的判断大小比较函数实现。所以如果是这样的:
return x > y ? 1 : -1;
那么就不符合此条件。
不过我们逻辑要比这个复杂,其实是这样一个排序条件。按照:
所以这个判断函数的问题是:
public compareFlightPrice(flightPrice o1, flightPrice o2){
// 非经停非共享
if (o1.getStopNumber() == 0 && !o1.isShare()) {
return -1;
} else if (o2.getStopNumber() == 0 && !o2.isShare()) {
return 1;
} else {
if (o1.getStopNumber() == 0) {
return -1;
} else if (o2.getStopNumber() == 0) {
return 1;
} else {
if (!o1.isShare()) {
return -1;
} else if (!o2.isShare()) {
return 1;
} else {
if (o1.getStopNumber() > 0) {
return -1;
} else if (o2.getStopNumber() > 0) {
return 1;
} else {
return 0;
}
}
}
}
}
这个函数有明显的先到先得的问题,比如对于compareFlightPrice(a, b) ,如果ab都是非共享非经停,那么这个就会把a排到前面,但如果调用compareFlightPrice(b, a) ,b又会排到前面,所以必须判断a是非共享非经停且b不是非共享非经停,才能让a排在前面。
当然除了改比较函数,还有一个解决方式是:给jvm添加启动参数。
-Djava.util.Arrays.useLegacyMergeSort=true
还需要注意的是,并不一定你的集合中存在相等的元素,并且比较函数不符合上面的严谨定义,就一定会稳定浮现此异常,实际上我们在生产环境出现此异常的概率很小,毕竟java并不会蠢到先去把整个数组都校验一遍,实际上它是在排序的过程中发现你不符合此条件的。所以有可能某种集合顺序让你刚好绕过了此判断。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。
# java
# 异常
# 抛出异常
# 异常处理
# 解决启动Azkaban报错问题:java.lang.NoSuchMethodError: com.g
# 详解java代码中init method和destroy method的三种使用方式
# Java上传文件错误java.lang.NoSuchMethodException的解决办法
# java中Class.getMethods()和Class.getDeclaredMethods()
# 详解Java中Method的Invoke方法
# 解决 java.lang.NoSuchMethodError的错误
# 解析Java中的Field类和Method类
# java.lang.AbstractMethodError: org.apache.xerces.d
# Java反射机制及Method.invoke详解
# Java Method类及invoke方法原理解析
# 后来者居上
# 先到
# 就会
# 先得
# 是这样
# 过程中
# 的是
# 都是
# 找到了
# 起飞时间
# 是在
# 是因为
# 我在
# 让你
# 有可能
# 就有
# 就不
# 我又
# 会在
# 不去
相关文章:
如何快速搭建FTP站点实现文件共享?
Python多线程使用规范_线程安全解析【教程】
电商网站制作公司有哪些,1688网是什么意思?
如何规划企业建站流程的关键步骤?
如何选择高效稳定的ISP建站解决方案?
成都品牌网站制作公司,成都营业执照年报网上怎么办理?
北京制作网站的公司,北京铁路集团官方网站?
如何快速搭建二级域名独立网站?
建站之星导航配置指南:自助建站与SEO优化全解析
无锡营销型网站制作公司,无锡网选车牌流程?
建站与域名管理如何高效结合?
建站主机选择指南:服务器配置与SEO优化实战技巧
网站制作与设计教程,如何制作一个企业网站,建设网站的基本步骤有哪些?
西安制作网站公司有哪些,西安货运司机用的最多的app或者网站是什么?
jQuery 常见小例汇总
如何登录建站主机?访问步骤全解析
如何通过.red域名打造高辨识度品牌网站?
已有域名能否直接搭建网站?
高端云建站费用究竟需要多少预算?
网站制作知乎推荐,想做自己的网站用什么工具比较好?
建站中国官网:模板定制+SEO优化+建站流程一站式指南
魔毅自助建站系统:模板定制与SEO优化一键生成指南
c# Task.Yield 的作用是什么 它和Task.Delay(1)有区别吗
商务网站制作工程师,从哪几个方面把握电子商务网站主页和页面的特色设计?
如何在Mac上搭建Golang开发环境_使用Homebrew安装和管理Go版本
如何在阿里云高效完成企业建站全流程?
建站三合一如何选?哪家性价比更高?
建站主机是否属于云主机类型?
建站之星代理如何获取技术支持?
如何通过PHP快速构建高效问答网站功能?
建站之星在线客服如何快速接入解答?
公司网站制作价格怎么算,公司办个官网需要多少钱?
宝塔建站助手安装配置与建站模板使用全流程解析
如何获取开源自助建站系统免费下载链接?
PHP 500报错的快速解决方法
制作农业网站的软件,比较好的农业网站推荐一下?
如何做网站制作流程,*游戏网站怎么搭建?
如何有效防御Web建站篡改攻击?
油猴 教程,油猴搜脚本为什么会网页无法显示?
哪家制作企业网站好,开办像阿里巴巴那样的网络公司和网站要怎么做?
成都网站制作报价公司,成都工业用气开户费用?
网站制作模板下载什么软件,ppt模板免费下载网站?
建站主机是否等同于虚拟主机?
北京建设网站制作公司,北京古代建筑博物馆预约官网?
杭州银行网站设计制作流程,杭州银行怎么开通认证方式?
免费制作海报的网站,哪位做平面的朋友告诉我用什么软件做海报比较好?ps还是cd还是ai这几个软件我都会些我是做网页的?
建站之星IIS配置教程:代码生成技巧与站点搭建指南
Swift中switch语句区间和元组模式匹配
如何高效生成建站之星成品网站源码?
C++如何使用std::optional?(处理可选值)
*请认真填写需求信息,我们会在24小时内与您取得联系。