我们有带有复杂比较器的代码,这些代码已用于在整个应用程序中对 java 对象进行排序。从历史上看,这些都是有效的,但是自从在 Java 7 中引入 TimSort 后,我们偶尔会发现比较方法违反了它的一般约定!错误..取决于对象中保存的数据。
这是我们的一个传统比较器的示例(可能已有近十年的历史 - 请原谅狡猾):
public int compare(TemplateBean b1, TemplateBean b2) {
// avoid null pointer exceptions
if (b1 == null && b2 == null) return 0;
if (b1 == null) return 1;
if (b2 == null) return -1;
int cmp = 0;
if ("UNATTACHED".equals(b1.getStatusCode()) &&
!"UNATTACHED".equals(b2.getStatusCode())) {
cmp = 1;
}
if (!"UNATTACHED".equals(b1.getStatusCode()) &&
"UNATTACHED".equals(b2.getStatusCode())) {
cmp = -1;
}
if (!"UNATTACHED".equals(b1.getStatusCode()) &&
!"UNATTACHED".equals(b2.getStatusCode()) &&
!"FIELDSIMPLE".equals(b1.getRefRltshpTypeCode()) &&
!"FIELDSIMPLE".equals(b2.getRefRltshpTypeCode()) &&
!"CUSTOM".equals(b1.getRefRltshpTypeCode()) &&
!"CUSTOM".equals(b2.getRefRltshpTypeCode()) &&
!"FUNCTION".equals(b1.getRefRltshpTypeCode()) &&
!"FUNCTION".equals(b2.getRefRltshpTypeCode())) {
String parent1 = b1.getGroupCode() == null ? "" : b1.getGroupCode().toUpperCase();
String parent2 = b2.getGroupCode() == null ? "" : b2.getGroupCode().toUpperCase();
cmp = parent1.compareTo(parent2);
}
if (cmp == 0) {
Integer i1 = b1.getSortOrder() == null ? Const.ZERO : b1.getSortOrder();
Integer i2 = b2.getSortOrder() == null ? Const.ZERO : b2.getSortOrder();
cmp = i1.compareTo(i2);
}
if (cmp == 0) {
String s1 = b1.getShortDescription();
if (s1 == null) s1 = "";
String s2 = b2.getShortDescription();
if (s2 == null) s2 = "";
cmp = s1.compareToIgnoreCase(s2);
}
return cmp; }
所以,我想复制这个功能,但是使用一个可以安全地与 TimSort 一起使用的 Comparator。
从代码中您可以看到此比较有多个级别..
- 它将比较组代码。
- 如果组代码相同,它将比较排序顺序。
- 如果排序顺序相同,它将比较描述。
这意味着它将返回特定级别的比较结果。这可能是两个字符串或两个整数的比较结果。我认为这就是破坏 TimSort 的原因。
我能够让这个比较器解决一般合同问题的唯一方法是对 bean 的内容进行哈希处理并执行字符串比较。其他想法包括编写我们自己的排序函数。当然有更好的方法吗?
是否应该以另一种方式构造 bean 来支持这一点?