ifeilong / feilong-core

:gem: Reduce development, Release ideas
Apache License 2.0
529 stars 155 forks source link

SortUtil.sortMapByValueDesc(Map<String, Integer>) 会报异常 #643

Closed venusdrogon closed 7 years ago

venusdrogon commented 7 years ago

SortUtil.sortMapByValueDesc(Map<String, Integer>) 会报异常

java.lang.IllegalArgumentException: Comparison method violates its general contract!
venusdrogon commented 7 years ago

#
#Sat Jul 29 05:03:42 CST 2017
chacuo.net=10
2980.com=44
nb.com=21
stu.pkuschool.edu.cn=4
bupt.edu.cn=4
2008.sina.com=16
hotmail.com.tw=8
qzone.qq.com=4
hotmail.ca=4
qibaodwight.org=4
sohu.com.cn=4
hotmail.co.uk=16
162.com=9
vipqq.com=4
zsyyu.com=4
live.hk=21
bertelsmann.com.cn=8
100tal.com=4
136.com=44
51.com=27
gamil.com=22
shou.com=4
googlemail.com=6
hanmail.net=14
yahoo.com.sg=13
wo.com.cn=59
petrochina.com.cn=13
citicbank.com=5
icluod.com=5
dchigh-suzhou.cn=4
3g.sina.cn=4
cntv.cn=9869
pingan.com.cn=7
cmbc.com.cn=22
qqcn.com=5
my.com=20
aol.com=25
iplabel.com=4
yinji.com.cn=5
xiaomitq.com=6
tencent.com=4
souhu.com=7
mail.qq.com=4
mtr.bj.cn=4
sinotrans.com=6
csvw.com=8
dragonip.com=4
miamioh.edu=4
ctrip.com=6
128.com=8
citiz.net=15
ge.com=4
mail.uic.edu.hk=4
live.com=753
186.com=4
sinopec.com=17
link.cuhk.edu.cn=9
hotmail.com.cn=4
sins.com=4
yonyou.com=8
buaa.edu.cn=8
aim.com=4
kocball.com=37
we.com=11
adds.com=4
yofc.com=4
qq163.com=17
eyou.com=44
pku.edu.cn=25
pp.com=154
marchrainir.com=38
mails.tsinghua.edu.cn=9
1633.com=5
yahoo.co.id=7
ceair.com=10
yahoo.com.au=8
huawei.com=10
yahoo.co.uk=19
neusoft.com=5
tongji.edu.cn=7
le.com=4
qq.163.com=4
nate.com=5
12312.com=4
ruc.edu.cn=5
pousheng.com=9
174.com=4
student.xjtlu.edu.cn=7
rocketmail.com=8
wdhac.com.cn=4
ihg.com=4
263.com=21
tcl.com=5
aw.com=12
outlook.com=2642
mickey.pro=20
hotmail.fr=10
123.com=36
vip.126.com=23
q163.com=4
anyirs.com=20
163.co=18
163.cm=22
baidu.com=7
fox.com=7
wo.cn=86
msn.cn=121
livemail.tw=5
aliyun.com.cn=14
adidas-group.com=23
sing.com=4
cnooc.com.cn=8
stu.edu.cn=11
yahoo.fr=5
flyme.cn=4
daum.net=6
test.com=52
smmail.cn=6
cofco.com=4
externals.adidas-group.com=4
sjtu.edu.cn=13
zpmc.net=4
qw.com=5
scn.com.cn=5
csair.com=11
i.softbank.jp=4
gzmtr.com=5
china.com.cn=34
ymail.com=27
yahoo.es=4
bysoftchina.com=15
me.com=678
263.net=76
163.com.cn=41
live.jp=5
mac.com=5
dingtalk.com=5
139.cn=10
kimo.com=4
qq.com.cn=296
nottingham.edu.cn=11
cnpc.com.cn=6
cmbchina.com=10
hotmail.co.jp=12
fixplus.cn=13
qq.vip.com=25
cn.ibm.com=4
ele.me=4
99.com=8
173.com=4
topsports.com.cn=4
hnair.com=5
mail.ustc.edu.cn=6
netease.com=6
chinaunicom.cn=18
nenu.edu.cn=4
26.com=5

java.lang.IllegalArgumentException: Comparison method violates its general contract!
    at java.util.TimSort.mergeLo(TimSort.java:747)
    at java.util.TimSort.mergeAt(TimSort.java:483)
    at java.util.TimSort.mergeCollapse(TimSort.java:410)
    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)
    at com.feilong.core.util.SortUtil.sortList(SortUtil.java:346)
    at com.feilong.core.util.SortUtil.sortMap(SortUtil.java:913)
    at com.feilong.core.util.SortUtil.sortMapByValueDesc(SortUtil.java:828)
    at com.feilong.core.util.sortutiltest.SortMapByValueDescTest.testSortByValueDesc12(SortMapByValueDescTest.java:63)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
venusdrogon commented 7 years ago

    @SuppressWarnings({ "rawtypes", "unchecked" })
    private int compareWithSameValue(T t1,T t2){
        //ObjectUtils.compare(t1, t2, false)
        //如果对象实现了 Comparable 接口, 那么直接强转比较
        //return isInstance(t1, Comparable.class) ? ((Comparable) t1).compareTo(t2) : 1;
        return isInstance(t1, Comparable.class) ? ObjectUtils.compare((Comparable) t1, (Comparable) t2, false) : 1;
    }

在于 #631 改的时候, 从hash 改成了 1

venusdrogon commented 7 years ago

http://blog.csdn.net/ghsau/article/details/42060651

http://blog.csdn.net/ghsau/article/details/42012365

venusdrogon commented 7 years ago

Map 的 SimpleEntry 没有实现 Comparable 接口


 public static class SimpleEntry<K,V>
        implements Entry<K,V>, java.io.Serializable
    {
        private static final long serialVersionUID = -8499721149061103585L;

        private final K key;
        private V value;

        /**
         * Creates an entry representing a mapping from the specified
         * key to the specified value.
         *
         * @param key the key represented by this entry
         * @param value the value represented by this entry
         */
        public SimpleEntry(K key, V value) {
            this.key   = key;
            this.value = value;
        }

        /**
         * Creates an entry representing the same mapping as the
         * specified entry.
         *
         * @param entry the entry to copy
         */
        public SimpleEntry(Entry<? extends K, ? extends V> entry) {
            this.key   = entry.getKey();
            this.value = entry.getValue();
        }

        /**
         * Returns the key corresponding to this entry.
         *
         * @return the key corresponding to this entry
         */
        public K getKey() {
            return key;
        }

        /**
         * Returns the value corresponding to this entry.
         *
         * @return the value corresponding to this entry
         */
        public V getValue() {
            return value;
        }

        /**
         * Replaces the value corresponding to this entry with the specified
         * value.
         *
         * @param value new value to be stored in this entry
         * @return the old value corresponding to the entry
         */
        public V setValue(V value) {
            V oldValue = this.value;
            this.value = value;
            return oldValue;
        }

        /**
         * Compares the specified object with this entry for equality.
         * Returns {@code true} if the given object is also a map entry and
         * the two entries represent the same mapping.  More formally, two
         * entries {@code e1} and {@code e2} represent the same mapping
         * if<pre>
         *   (e1.getKey()==null ?
         *    e2.getKey()==null :
         *    e1.getKey().equals(e2.getKey()))
         *   &amp;&amp;
         *   (e1.getValue()==null ?
         *    e2.getValue()==null :
         *    e1.getValue().equals(e2.getValue()))</pre>
         * This ensures that the {@code equals} method works properly across
         * different implementations of the {@code Map.Entry} interface.
         *
         * @param o object to be compared for equality with this map entry
         * @return {@code true} if the specified object is equal to this map
         *         entry
         * @see    #hashCode
         */
        public boolean equals(Object o) {
            if (!(o instanceof Map.Entry))
                return false;
            Map.Entry e = (Map.Entry)o;
            return eq(key, e.getKey()) && eq(value, e.getValue());
        }

        /**
         * Returns the hash code value for this map entry.  The hash code
         * of a map entry {@code e} is defined to be: <pre>
         *   (e.getKey()==null   ? 0 : e.getKey().hashCode()) ^
         *   (e.getValue()==null ? 0 : e.getValue().hashCode())</pre>
         * This ensures that {@code e1.equals(e2)} implies that
         * {@code e1.hashCode()==e2.hashCode()} for any two Entries
         * {@code e1} and {@code e2}, as required by the general
         * contract of {@link Object#hashCode}.
         *
         * @return the hash code value for this map entry
         * @see    #equals
         */
        public int hashCode() {
            return (key   == null ? 0 :   key.hashCode()) ^
                   (value == null ? 0 : value.hashCode());
        }

        /**
         * Returns a String representation of this map entry.  This
         * implementation returns the string representation of this
         * entry's key followed by the equals character ("<tt>=</tt>")
         * followed by the string representation of this entry's value.
         *
         * @return a String representation of this map entry
         */
        public String toString() {
            return key + "=" + value;
        }

    }
venusdrogon commented 7 years ago

最早期的一个版本 see 551249bb976ea0f242c66c5e00504b9dcbbcb542