-Djava.util.Arrays.useLegacyMerg

2020-12-20  本文已影响0人  zh_harry
java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeHi(TimSort.java:868)
at java.util.TimSort.mergeAt(TimSort.java:485)
at java.util.TimSort.mergeCollapse(TimSort.java:408)
at java.util.TimSort.sort(TimSort.java:214)
at java.util.TimSort.sort(TimSort.java:173)
at java.util.Arrays.sort(Arrays.java:659)
at java.util.Collections.sort(Collections.java:217)

在 JDK7 版本以上,Comparator 要满足自反性,传递性,对称性,不然 Arrays.sort,

Collections.sort 会报 IllegalArgumentException 异常。

说明:

1) 自反性:x,y 的比较结果和 y,x 的比较结果相反。

2) 传递性:x>y,y>z,则 x>z。

3) 对称性:x=y,则 x,z 比较结果和 y,z 比较结果相同。

重现

package com.sparrow.jdk.collections;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

/**
 * -Djava.util.Arrays.useLegacyMergeSort=true
 */
public class DictionaryTest {
    public static void main(String[] args) {
        //exception
        int[] array = new int[]{1, 2, 3, 2, 2, 3, 2, 3, 2, 2, 3, 2, 3, 3, 2, 2, 2, 2, 2, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};

        array = new int[]{2, 3, 2, 2, 3, 2, 3, 2, 2, 3, 2, 3, 3, 2, 2, 2, 2, 2, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};

        List<DictionaryEntry> list = new ArrayList<>();
        Set<DictionaryEntry> set = new TreeSet<>();
        for (int i = 0; i < array.length; i++) {
            DictionaryEntry entry = new DictionaryEntry();
            entry.setItemId(i);
            entry.setScore(new BigDecimal(array[i]));
            list.add(entry);
            set.add(entry);
        }
        long current = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) {
            //System.out.println(set.size());
            Collections.sort(list);
            //System.out.println(list.size());
        }
        System.out.println(System.currentTimeMillis() - current);
    }

    public static class DictionaryEntry implements Comparable<DictionaryEntry> {
        public DictionaryEntry() {
        }

        private Integer itemId;
        private BigDecimal score;

        public BigDecimal getScore() {
            return score;
        }

        public void setScore(BigDecimal score) {
            if (score != null) {
                this.score = score.setScale(5, RoundingMode.HALF_UP);
            } else {
                this.score = new BigDecimal(0);
            }
        }

        public Integer getItemId() {
            return itemId;
        }

        public void setItemId(Integer itemId) {
            this.itemId = itemId;
        }

        @Override
        public int compareTo(DictionaryEntry o) {
            //tree set o.score.compareTo(this.score)==0时去重
            //手动设置非0时,throw new IllegalArgumentException("Comparison method violates its general contract!");
            //-Djava.util.Arrays.useLegacyMergeSort=true 解决兼容
            return o.score.compareTo(this.score) == 0 ? -1 : o.score.compareTo(this.score);
        }
    }
}

上一篇下一篇

猜你喜欢

热点阅读