我正在实现一个简单类的compareTo()
方法(以便能够使用Java平台提供的Collections.sort()
等好东西):
public class Metadata implements Comparable<Metadata> {
private String name;
private String value;
// Imagine basic constructor and accessors here
// Irrelevant parts omitted
}
我希望这些对象的自然排序为:1)按名称排序和2)如果名称相同则按值排序; 两个比较应该是不区分大小写的。 对于两个字段,均允许使用空值,因此 compareTo
不得在这些情况下中断。
我想到的解决方案大致如下(我在这里使用“守卫条件”,而其他人可能更喜欢单个返回点,但这并不重要):
// 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);
}
这可以完成任务,但是我对这段代码并不完全满意。不可否认的是,它并不是非常复杂,但是相当啰嗦和乏味。
问题是,如何使此 less verbose(同时保留功能)? 随意参考Java标准库或Apache Commons,如果它们有用的话。 使它(有点)更简单的唯一选择是实现自己的“NullSafeStringComparator”,并将其应用于比较两个字段吗?
修改1-3:Eddie 是对的;已修复上述“两个名称都为空”的情况。
About the accepted answer
我在2009年问过这个问题,当然是在Java 1.6上,并且当时 Eddie 提供的纯JDK解决方案 是我首选的被接受答案。直到现在(2017年)我才有时间去更改它。
还有 第三方库的解决方案 ——2009 年的一个 Apache Commons Collections 和 2013 年的一个 Guava 都是我发布的,曾经在某个时间点我更喜欢它们。
我现在将Lukasz Wiktor的干净的Java 8解决方案设为了被接受的答案。如果是在Java 8上,那肯定应该优先考虑这种解决方案,而现在Java 8几乎对所有项目都可用。