wilsonlee February 2016

Comparison method violates its general contract

I'm trying to sort a list. I used Collections.sort(list), and I got an IllegalArgumentException Exception.
I know this works on jdk6 and jdk7 is using TimSort. The rules I got is below. I think I got it right, but it doesn't work.

Is there anyone can give me a situation where my code doesn't work? Thanks a lot

RULES:

> 1.sgn(compare(x, y)) == -sgn(compare(y, x))
> 
> 2.((compare(x, y)>0) && (compare(y, z)>0)) implies compare(x, z)>0
> 
> 3.compare(x, y)==0 implies that sgn(compare(x, z))==sgn(compare(y, z)) for all z





//StringUtil.isBlank(str) return if str==null||str.trim().length()==0
@Override
public int compareTo(NovelChapter o) {
    if(o == null){
        return 1;
    }
    else if(o.equals(this) || this == o){
        return 0;
    }

    if(!StringUtil.isBlank(o.getSourceUrl())&& !StringUtil.isBlank(this.getSourceUrl())){
        if(o.getSourceUrl().length() != this.getSourceUrl().length()){
            return o.getSourceUrl().compareTo(this.getSourceUrl());
        }
        else{
            return o.getSourceUrl().compareTo(this.getSourceUrl()) * (-1);
        }
    }
    else if(!StringUtil.isBlank(o.getSourceUrl())&& !StringUtil.isBlank(this.getSourceUrl())){
        return 1;
    }
    else if(!StringUtil.isBlank(o.getSourceUrl())&& StringUtil.isBlank(this.getSourceUrl())){
        return -1;
    }
    else{
        return 0;
    }
}

BTW, System.setProperty("java.util.Arrays.useLegacyMergeSort", "true"); is using jdk6, it does not solve the problem itself.

================================================

thanks for all the answers,and I changed the code,now it throw NPE .Is it better now ?But it still give me the same Exception.

@Override
public int compareTo(NovelChapter o) {

    if(o == null){
        throw new NullPointerException();
    }else if(o.equals(this) || this == o){        

Answers


Mehrdad Nurolahzade February 2016

From Comparable Javadoc:

Note that null is not an instance of any class, and e.compareTo(null) should throw a NullPointerException even though e.equals(null) returns false.


Stephen C February 2016

I can't see the specific cause of that exception, but there are a couple of problems in the code you have shown us.

  1. The compareTo method should not be used on null, so your special handling of null should not be there. The comparator >>should<< throw an NPE. (And the corollary is that you should not be attempting to sort arrays / collections that contain null values.)

  2. Your use of trim looks inconsistent. You trim when you look for "blank" URLs, but not when comparing "non-blank" URLs. Weird.

I would add that your code is verbose and inefficient. Rather than repeatedly calling that isBlank utility in a chain of if / else statements you should simply convert the two URLs into strings (I'm guessing) that can be compared directly.

Finally, the fact that you have to have an isBlank method at all says (to me) that the rest of your code is doing a poor job of maintaining data consistency. There should be exactly one representation that means "no source URL" ... not (at least) three.


There are a number of possible causes of this problem that can only be eliminated by examining the complete classes involved ... starting with NovelChapter and whatever it is that getSourceUrl() returns.

Post Status

Asked in February 2016
Viewed 2,801 times
Voted 4
Answered 2 times

Search




Leave an answer