处理 Comparable接口不严谨导致Comparison method violates its general contract!

本文主旨是记录问题解决过程

出错的日志

Shutting down VM
--------- beginning of crash
FATAL EXCEPTION: main
Process: com.gezbox.deliver, PID: 25572
java.lang.IllegalArgumentException: Comparison method violates its general contract!
AndroidRuntime:     at java.util.TimSort.mergeLo(TimSort.java:773)
AndroidRuntime:     at java.util.TimSort.mergeAt(TimSort.java:510)
AndroidRuntime:     at java.util.TimSort.mergeForceCollapse(TimSort.java:453)
AndroidRuntime:     at java.util.TimSort.sort(TimSort.java:250)
AndroidRuntime:     at java.util.Arrays.sort(Arrays.java:1523)
AndroidRuntime:     at java.util.Collections.sort(Collections.java:238)
AndroidRuntime:     at com.zzz.XXXFragment.refreshDate(XXXFragment.java:203)
AndroidRuntime:     at com.zzz.XXXFragment$2.onSuccess(XXXFragment.java:152)
AndroidRuntime:     at com.zzz.XXXFragment$2.onSuccess(XXXFragment.java:147)
AndroidRuntime:     at com.gezbox.net.Callback.onResponse(Callback.java:79)
AndroidRuntime:     at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:70)
AndroidRuntime:     at android.os.Handler.handleCallback(Handler.java:754)
AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:95)
AndroidRuntime:     at android.os.Looper.loop(Looper.java:165)
AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:6365)
AndroidRuntime:     at java.lang.reflect.Method.invoke(Native Method)
AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:883)
AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773)

原因

  • JDK7中的Collections.Sort方法实现中,你的返回值需要严谨全面
  • 如果两个值是相等的,那么compare方法需要返回0,否则 可能 会在排序时抛错,而JDK6是没有这个限制的。
  • 在在 JDK7 版本以上,Comparator 要满足自反性,传递性,对称性

代码使用的范例

说明:
1) 自反性:x,y 的比较结果和 y,x 的比较结果相反。
2) 传递性:x>y,y>z,则 x>z。
3) 对称性:x=y,则 x,z 比较结果和 y,z 比较结果相同

对比代码一般是这样的结构,写一段放着看看

Collections.sort(dataList, new Comparator() {
    @Override
    public int compare(PackageInfo item1, PackageInfo item2) {
        return xxxxx.compare(xxxxx);
    }
});

有个简单的解决办法

  • 找出所有的条件语句
  • 针对所有条件,列出所有的可能情况。然后遍历一遍,覆盖所有的路径

上代码

范例

Collections.sort(dataList, new Comparator.PackageInfo>() {
            @Override
            public int compare(ProcessingOrderResponse.PackageInfo item1, ProcessingOrderResponse.PackageInfo item2) {
                if (TextUtils.equals(mContext.getResources().getString(R.string.task_order_return), item1.packageNo)) {
                    return 1;
                } else if (TextUtils.equals(mContext.getResources().getString(R.string.task_order_return), item2.packageNo)) {
                    return -1;
                } else {
                    return item1.packageNo.compareTo(item2.packageNo);
                }
            }
        });

修改后的

Collections.sort(dataList, new Comparator.PackageInfo>() {
            @Override
            public int compare(ProcessingOrderResponse.PackageInfo item1, ProcessingOrderResponse.PackageInfo item2) {
                if (TextUtils.equals(mContext.getString(R.string.task_order_return), item1.packageNo)
                        && TextUtils.equals(mContext.getString(R.string.task_order_return), item2.packageNo)) {
                    return 0;
                } else if (!TextUtils.equals(mContext.getString(R.string.task_order_return), item1.packageNo)
                        && TextUtils.equals(mContext.getString(R.string.task_order_return), item2.packageNo)) {
                    return 1;
                } else if (TextUtils.equals(mContext.getString(R.string.task_order_return), item1.packageNo)
                        && !TextUtils.equals(mContext.getString(R.string.task_order_return), item2.packageNo)) {
                    return -1;
                } else {
                    if (item1.packageNo.compareTo(item2.packageNo) > 0) {
                        return 1;
                    } else if (item1.packageNo.compareTo(item2.packageNo) == 0) {
                        return 0;
                    } else {
                        return -1;
                    }
                }
            }
        });

简单说明

这里有三个判断条件
两个TextUtil.equals 以及String.compareTo
解决思路是
想讲两个TextUtil.equals这的所有路径都遍历,得到4个状态,分别给出10,-1这几个返回值
剩下的String.compareTo也遍历一遍,给出10,-1三个返回值

网上找了一圈,本来想看看java的源码,结果。。。。没找到源码,有知道的朋友麻烦告诉我一下,在此先谢过

你可能感兴趣的:([工作记录])