【发布时间】:2010-10-03 16:00:54
【问题描述】:
我正在为这样一个简单的类实现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 在这些情况下不得中断。
想到的解决方案大致如下(我在这里使用“保护条款”,而其他人可能更喜欢单个返回点,但这不是重点):
// 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 上,当时 the pure JDK solution by Eddie 是我首选的公认答案。直到现在(2017 年),我才开始改变它。
还有3rd party library solutions——一个 2009 年的 Apache Commons Collections 和一个 2013 年的 Guava,都是我发布的——我在某个时间点确实更喜欢它们。
我现在将干净的 Java 8 solution by Lukasz Wiktor 设为已接受的答案。如果在 Java 8 上,这绝对应该是首选,而且现在几乎所有项目都应该使用 Java 8。
【问题讨论】:
标签: java refactoring comparison null compareto