简体   繁体   中英

How does Java detect comparator contract violation?

I find it surprising that Java can sometimes check the comparator contract for you.

For example, when you write an order relation that does not follow transitivity, you get

java.lang.IllegalArgumentException: Comparison method violates its general contract!

How is it possible to check such violation? How does Java implement it?


(See this question if you don't know what I'm talking about)

You didn't specifically say when you get this exception. I assume that you're getting this when you do a Collections.sort call with your own Comparator as an argument, because that's where I've been able to find this error in the Java source code.

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/util/TimSort.java#773

(TimSort is the implementation used for Collections.sort )

When your Comparator is inconsistent (the result of compare(a,b) is not consistent with the result of compare(b,a) ) or not stable - doesn't return the same outcome for the same input, you'll get an internal inconsistency in the temporary state that the TimSort method keeps.

The algorithm detects this internal inconsistency and throws the Exception:

772        } else if (len1 == 0) {
773            throw new IllegalArgumentException(
774                "Comparison method violates its general contract!");
775        } 

Note there is no guarantee that you will get this exception when your Comparator breaks its contract (that would be cool for a unit test of your comparator).

It may simply not be incorrect for the input that you happened to pass to a particular call to Collections.sort , or the inconsistent output of your Comparator may simply not result in an internal inconsistency in the TimSort method. In that case, it's still possible that the resulting sort order is incorrect, but you're not guaranteed to get an exception.

Of course, it cannot prove that by inspecting your code!

The violation is detected for specific inputs and in some code branches. For exmaple

if( compare(x,y)==0 && compare(y,x)!=0 )
    throw IllegalArgumentException: Comparison method violates its general contract!

Just check the actual source where the exception is thrown, eg http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/util/TimSort.java#772

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