我正在为一个简单的类实现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)如果名称相同,则按值排序。这两种比较都应该不区分大小写。对于这两个字段,null值是完全可以接受的,所以在这些情况下,{{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);
}
这段代码可以完成任务,但我对它并不完全满意。诚然,它并不是非常复杂,但相当冗长和乏味。
问题是,你如何使其更简洁(同时保留功能)?如果有必要,可以参考Java标准库或Apache Commons。是否唯一的简化选项是实现自己的“NullSafeStringComparator”,并将其应用于比较两个字段?
编辑1-3:Eddie是正确的;已修复上面的“两个名称都为空”的情况
关于被接受的答案
我在2009年提出了这个问题,在当时的Java 1.6上,当时Eddie的纯JDK解决方案是我首选的被接受的答案。直到现在(2017年),我才有机会更改它。
还有第三方库解决方案——我曾经喜欢的2009年Apache Commons Collections和2013年Guava解决方案,现在我将干净的Lukasz Wiktor的Java 8解决方案作为被接受的答案。如果使用Java 8,则应该优先考虑该解决方案,现在Java 8应该可用于几乎所有项目。