简体   繁体   中英

Comparator not working

We have written following code which is not working for Comparator compare method.

public int compare(Object o1, Object o2)
{
    if (o2 == null) return 1;
    else if (o1 == null) return -1;

    MailObject a = (MailObject)o1;
    MailObject b = (MailObject)o2;
    return a.getType() < b.getType()? 1 : -1;
}

where the getType() method returns an integer value. and following code is working fine

public int compare(Object o1, Object o2)
{
    if (o2 == null) return 1;
    else if (o1 == null) return -1;

    MailObject a = (MailObject)o1;
    MailObject b = (MailObject)o2;
    return a.getType() - b.getType();
}

If we remove ternary operator in return statement, then it is working fine. If we add equal check, then also it is working fine. Why?

first block of code giving following exception:

07:45:22 ERROR c.c.servlet.MyServlet - Comparison method violates its general contract!
java.lang.IllegalArgumentException: Comparison method violates its general contract!
               at java.util.TimSort.mergeHi(Unknown Source) ~[na:1.8.0_25]
               at java.util.TimSort.mergeAt(Unknown Source) ~[na:1.8.0_25]
               at java.util.TimSort.mergeCollapse(Unknown Source) ~[na:1.8.0_25]
               at java.util.TimSort.sort(Unknown Source) ~[na:1.8.0_25]
               at java.util.Arrays.sort(Unknown Source) ~[na:1.8.0_25]
               at java.util.List.sort(Unknown Source) ~[na:1.8.0_25]
               at java.util.Collections.sort(Unknown Source) ~[na:1.8.0_25]

Your initial implementation breaks the general contract for Comparator s by not dealing correctly (ie, returning 0) when the two types are equal.

Instead of trying to implement the comparison logic between two integers by yourself, why not let Integer do what it knows best ?

return Integer.compare(a.getType(), b.getType());

You forget to return 0 for equal values.

Following always true for non-null x:

(x < x ? 1 : -1) == -1

Both your comparators are NOT the same, they are actually opposite of each other.

In the first case, if a is lesser, you return a positive value .

In second, if a is lesser, you return a negative value .

You could try the following code which would take into account if they are equal, which this will not. It will return -1 if they are equal or b is greater than a. So try...

return a.getType() < b.getType()? -1 : a.getType() > b.getType()? 1 : 0;

In this it tests if a is less than b, if it is, it returns -1, if it is not, it then tests if a is greater than b, if that is true it returns 1, if not they must be equal so it returns 0;

Of course, you can change those values to whatever suits you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM