我正在为这样一个简单的类实现 compareTo()
方法(为了能够使用 Collections.sort()
和 Java 平台提供的其他好东西) :
public class Metadata implements Comparable<Metadata> {
private String name;
private String value;
// Imagine basic constructor and accessors here
// Irrelevant parts omitted
}
我希望这些对象的 自然秩序是: 1)按名称排序,2)如果名称相同,则按值排序; 这两种比较应该不区分大小写。对于这两个字段,空值是完全可以接受的,因此在这些情况下,compareTo
不能中断。
我想到的解决方案大致如下(我在这里使用了“ Guard 子句”,而其他人可能更喜欢单一的返回点,但那不是重点) :
// primarily by name, secondarily by value; null-safe; case-insensitive
public int compareTo(Metadata other) {
if (this.name == null && other.name != null){
return -1;
}
else if (this.name != null && other.name == null){
return 1;
}
else if (this.name != null && other.name != null) {
int result = this.name.compareToIgnoreCase(other.name);
if (result != 0){
return result;
}
}
if (this.value == null) {
return other.value == null ? 0 : -1;
}
if (other.value == null){
return 1;
}
return this.value.compareToIgnoreCase(other.value);
}
这样就可以了,但是我对这个代码不是很满意。不可否认,它不是 非常复杂的,但是相当冗长和乏味。
问题是,你怎么才能不这么冗长呢(同时保留其功能) ?如果有帮助,请随意参考 Java 标准库或 ApacheCommons。使这个(稍微)简单一点的唯一选择是实现我自己的“ NullSafeStringComparator”,并应用它来比较两个字段吗?
编辑1-3 : Eddie 是对的; 修正了上面“两个名字都为空”的情况
我在2009年的时候问过这个问题,当然是在 Java 1.6上,当时 Eddie 的纯 JDK 解决方案是我首选的答案。直到现在(2017年) ,我才抽出时间来改变这一点。
还有我发布的 第三方图书馆解决方案ーー2009年的 Apache Commons Collections1和2013年的 Guava ーー我在某个时候的确更喜欢它们。
我现在使干净的 Java 8解决方案作者: Lukasz Wiktor接受的答案。如果在 Java8上,这肯定是首选的,而且现在几乎所有的项目都可以使用 Java8。