Java自定义Comparator触发Comparison method violates its general contract错误原因
比较器报错原因解析
核心原因:你的代码违反了Java比较器的强制契约
Java的Collections.sort底层默认使用TimSort算法,该算法要求自定义比较器必须严格遵守三条规则,否则就会抛出Comparison method violates its general contract异常:
- 自反性:任意元素a和自身比较,
compare(a,a)必须返回0 - 对称性:任意两个元素a、b,如果
compare(a,b) > 0,那么compare(b,a)必须 < 0,反之亦然 - 传递性:任意三个元素a、b、c,如果
compare(a,b) > 0且compare(b,c) > 0,那么compare(a,c)必须 > 0
你的代码问题点
当两个元素频率相同、数值也相等时,你的比较逻辑:
if(n1>=n2){ return -1; } return 1;
此时n1等于n2,你返回的是-1而非0,直接违反了前两条规则:
- 自己和自己比较返回-1,不符合自反性要求
- 假设a和b是两个相等的元素,
compare(a,b)返回-1,compare(b,a)也会返回-1,两个结果符号相同,完全不符合对称性要求
而网上的正确写法在n1等于n2时会返回n2-n1 = 0,完全符合所有契约要求,所以不会报错。
为什么前85个用例能通过
TimSort的一致性校验只有在特定数据规模、合并分区的时候才会触发,小数据量或者刚好排序过程没有触发校验逻辑的时候,错误不会暴露,当测试用例的数据规模变大、数据分布触发了校验逻辑,异常就会抛出。
内容的提问来源于stack exchange,提问作者Kavin_V
相关产品推荐
相关产品推荐

