前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Comparison method violates its general contract! 问题

Comparison method violates its general contract! 问题

作者头像
说故事的五公子
发布2022-09-19 14:56:48
2.3K1
发布2022-09-19 14:56:48
举报

引言

今天下午正在摸鱼,这时候突然客户在群里反馈,说今天数据没有了,催我赶紧去看,于是我连上客户服务器,打开今天的项目日志,看到了下面的错误 Comparison method violates its general contract

问题原因

花了几分钟解决,记录一下

先看下之前的代码,功能就是获取指定目录下最近修改的文件名称,里面用到了Arrays.sort 排序

代码语言:javascript
复制
/** 读取特定目录下最新的文件名称
 * @param filePath 文件路径
 * @return String
 */
public static String getLatestFile(String filePath ) {
    String latestFile = "";
    // 获取最新改动的文件名
    try {
        File path = new File(filePath);
        if (path.exists()) {
            // 列出该目录下所有文件和文件夹
            File[] files = path.listFiles();
            if (null == files || files.length <= 0) {
                return latestFile;
            }
            // 按照文件最后修改日期倒序排序
            Arrays.sort(files, (file1, file2) -> {
                Long result = file2.lastModified() - file1.lastModified();
                //先将Long的差值算出,然后视该值是否会超越int的最大值,然后返回不同结果
                return result>=Integer.MAX_VALUE?Integer.MAX_VALUE:result.intValue();
            });
            latestFile = files[0].getName();
        }else{
            log.error("the latest file path is not exist:"+filePath);
            latestFile = "";
        }
    } catch (Exception e) {
        log.info("getLatestFile error", e);
    }
    return latestFile;
}

这段代码乍一看功能可以实现,测试也没有问题,为什么报错?

在 JDK7 版本以上,Comparator 要满足自反性,传递性,对称性,不然 Arrays.sortCollections.sort 会报 IllegalArgumentException 异常。

  1. 自反性:x,y 的比较结果和 y,x 的比较结果相反,即 sgn(compare(x,y)) == -sgn(compare(y,x))
  2. 传递性:x > y,y > z,则 x > z,即 ((compare(x, y)>0) && (compare(y, z)>0)) implies compare(x, z)>0
  3. 对称性:x=y,则 x,z 比较结果和 y,z 比较结果相同。即 compare(x,y)==0 implies that sgn(compare(x,z))==sgn(compare(y,z)) for all z

解决方案

方法1

强制 JVM 使用老旧的 MergeSort,而非新的 TimSort。

(1) 可以在代码层面上进行声明

代码语言:javascript
复制
System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");

(2) 也可以在 JVM 的启动参数中声明

代码语言:javascript
复制
-Djava.util.Arrays.useLegacyMergeSort=true

方法2

修改代码,使得比较器 Comparator 满足新算法自反性、传递性、对称性的要求,建议使用方法二

代码语言:javascript
复制
public static String getLatestFile(String filePath ) {
    String latestFile = "";
    // 获取最新改动的文件名
    try {
        File path = new File(filePath);
        if (path.exists()) {
            // 列出该目录下所有文件和文件夹
            File[] files = path.listFiles();
            if (null == files || files.length <= 0) {
                return latestFile;
            }
            //       LOG.info("Files in "+fileName+", files num="+files.length);
            // 按照文件最后修改日期倒序排序
            Arrays.sort(files, (file1, file2) -> {
                Long f1 = file1.lastModified();
                Long f2 = file2.lastModified();
                // 这里改用 compareTo 方法
                return f2.compareTo(f1);
                //Long result = file2.lastModified() - file1.lastModified();
                //先将Long的差值算出,然后视该值是否会超越int的最大值,然后返回不同结果
                //return result>=Integer.MAX_VALUE?Integer.MAX_VALUE:result.intValue();
            });
            latestFile = files[0].getName();
        }else{
            log.error("the latest file path is not exist:"+filePath);
            latestFile = "";
        }
    } catch (Exception e) {
        log.info("getLatestFile error", e);
    }
    return latestFile;
}

compareTo 源码

代码语言:javascript
复制
public int compareTo(Long anotherLong) {
    return compare(this.value, anotherLong.value);
}

public static int compare(long x, long y) {
    return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-08-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引言
  • 问题原因
  • 解决方案
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档