java - 非法参数异常 : Comparison method violates general contract

标签 java sorting collections

很抱歉,又是一个问题,但我根本不明白这里发生了什么,或者我哪里出了问题。

概述:我有一个包含多个电影 - 对象的ArrayList。这些对象有一个日期和一个开始时间。我想按以下条件对它们进行排序,优先级如下所示:

  • 日期
  • 开始时间

但是这样做时,我收到以下错误:

java.lang.IllegalArgumentException: Comparison method violates its general contract!
    at java.util.TimSort.mergeHi(TimSort.java:864)
    at java.util.TimSort.mergeAt(TimSort.java:481)
    at java.util.TimSort.mergeForceCollapse(TimSort.java:422)
    at java.util.TimSort.sort(TimSort.java:219)
    at java.util.TimSort.sort(TimSort.java:169)
    at java.util.Arrays.sort(Arrays.java:2010)
    at java.util.Collections.sort(Collections.java:1883)
    at org.pbdevelopement.cineapp.MainActivity.sortByStartingTime(MainActivity.java:208)

我所拥有的: 我在 JavaFX 项目中也发生了同样的事情,但我使用 ArrayList.sort() 而不是 Collections.sort() 进行排序。我需要转换为 Collections.sort(),因为显然 Android 还不支持 ArrayList.sort() 方法。

这是启动排序并定义Comperator的方法:

private ArrayList<Movie> sortByStartingTime(ArrayList<Movie> list) {
    Collections.sort(list, new Comparator<Movie>() { //This line is MainActivity.java: 208  ;)
        @Override
        public int compare(Movie o1, Movie o2) {
            int comparison = o1.getDate().compareTo(o2.getDate());
            if (comparison == 0) {
                return o1.getStartingTime().compareTo(o2.getStartingTime());
            }
            return comparison;
        }
    });
    return list;
}

如您所见,我比较了电影中的两个日期,如果它们相等,我继续比较开始时间。 以下是我的 DateKeeperTimeKeeper 类中的两个 compare() 方法(我也许应该承认它们是自己编写的):

public int compareTo(DateKeeper toCompare) {
    Calendar startDate = getAsCalendar();
    Calendar endDate = toCompare.getAsCalendar();
    long diff = endDate.getTimeInMillis() - startDate.getTimeInMillis();//in Milli seconds
    return (int) (diff / (1000 * 60 * 60 * 24));
}

返回-101,因为我想使用此方法以及两个日期之间的差异。我已经阅读了 compare 方法,发现这应该不是问题。

public int compareTo(TimeKeeper toCompare) {
    int toReturn = Integer.compare(this.getValue(), toCompare.getValue());
    return toReturn;
}

getValue() 只是返回所谓的 MINUTES_OF_DAY

我不明白这如何违反了方法契约。据我所知,Comperator是传递的(或者不是?)自反的和对称的。那么为什么我会收到此错误消息?

最佳答案

您的问题是,您在减去后除以当天的毫秒数。这可能会导致两个节目相隔 <24 小时,但在不同的日子显示为同一天。 尝试:

public int compareTo(DateKeeper toCompare) {
    Calendar startDate = getAsCalendar();
    Calendar endDate = toCompare.getAsCalendar();
    long diff = (endDate.getTimeInMillis()/ (1000 * 60 * 60 * 24)) - (startDate.getTimeInMillis()/ (1000 * 60 * 60 * 24));//in Milli seconds
    return (int) diff;
}

或将两个日历对象上的时间设置为午夜

关于java - 非法参数异常 : Comparison method violates general contract,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35502728/

相关文章:

java - GeoAPIContext 崩溃

java - Java 中的继承是如何工作的?

python - 根据运算结果对元组列表进行排序(除法)

java - 从 map 中获取条目集

delphi - 编写通用的 TList 记录

java - 从两个数组列表中删除公共(public)值

java - 制作不可变的第三方类

java - 破译来自 Google Play 的崩溃报告

python - 简单插入排序中的逻辑僵局

list - Kotlin - 基于对象属性对 MutableList 进行排序