我有几个比较器
——一个用于日期
,一个用于小数,一个用于百分比,等等。
一开始我的十进制比较器是这样的:
class NumericComparator implements Comparator<String> {
@Override
public int compare(String s1, String s2) {
final Double i1 = Double.parseDouble(s1);
final Double i2 = Double.parseDouble(s2);
return i1.compareTo(i2);
}
}
生活很简单。当然,这不能处理字符串不可解析的情况。所以我改进了compare()
:
class NumericComparator implements Comparator<String> {
@Override
public int compare(String s1, String s2) {
final Double i1;
final Double i2;
try {
i1 = Double.parseDouble(s1);
} catch (NumberFormatException e) {
try {
i2 = Double.parseDouble(s2);
} catch (NumberFormatException e2) {
return 0;
}
return -1;
}
try {
i2 = Double.parseDouble(s2);
} catch (NumberFormatException e) {
return 1;
}
return i1.compareTo(i2);
}
}
生活更美好。测试感觉更可靠。但是,我的代码审阅者指出,“null
怎么样?”
太好了,所以现在我必须用 NullPointerException
重复上面的操作,或者在方法体前面加上:
if (s1 == null) {
if (s2 == null) {
return 0;
} else {
return -1;
}
} else if (s2 == null) {
return 1;
}
这个方法很庞大。最糟糕的是,我需要用 三个其他类 重复此模式,这些类比较不同类型的字符串并可能在解析时引发 三个其他异常。
我不是 Java 专家。有比复制和粘贴更干净、更简洁的解决方案吗?gasp?只要记录在案,我是否应该用正确性来换取不复杂性?
更新:有人建议处理null
值不是Comparator
的工作。由于排序结果显示给用户,我确实希望空值一致地排序。
最佳答案
您正在实现 Comparator<String>
. String
的方法,包括compareTo
扔一个NullPointerException
如果将空值交给他们,那么您也应该这样做。同样,Comparator
抛出 ClassCastException
如果参数的类型阻止它们被比较。我建议您实现这些继承的行为。
class NumericComparator implements Comparator<String> {
public int compare(String s1, String s2) {
final Double i1;
final Double i2;
if(s1 == null)
{
throw new NullPointerException("s1 is null"); // String behavior
}
try {
i1 = Double.parseDouble(s1)
} catch (NumberFormatException e) {
throw new ClassCastException("s1 incorrect format"); // Comparator behavior
}
if(s2 == null)
{
throw new NullPointerException("s2 is null"); // String behavior
}
try {
i2 = Double.parseDouble(s1)
} catch (NumberFormatException e) {
throw new ClassCastException("s2 incorrect format"); // Comparator behavior
}
return i1.compareTo(i2);
}
}
extracting a method 几乎可以重拾最初的优雅进行类型检查和转换。
class NumericComparator implements Comparator<String> {
public int compare(String s1, String s2) {
final Double i1;
final Double i2;
i1 = parseStringAsDouble(s1, "s1");
i2 = parseStringAsDouble(s2, "s2");
return i1.compareTo(i2);
}
private double parseStringAsDouble(String s, String name) {
Double i;
if(s == null) {
throw new NullPointerException(name + " is null"); // String behavior
}
try {
i = Double.parseDouble(s1)
} catch (NumberFormatException e) {
throw new ClassCastException(name + " incorrect format"); // Comparator behavior
}
return i;
}
}
如果您对异常消息不特别在意,则可以省略“name”参数。我敢肯定,您可以通过应用小技巧在这里少写一行或多写一个词。
你说你需要 repeat this pattern with three other classes which compare different types of strings and could raise three other exceptions
.在没有看到情况的情况下很难在那里提供细节,但你可以使用 "Pull Up Method"在我的一个版本上 parseStringAsDouble
成为NumericComparator
的共同祖先它本身实现了 java 的 Comparator
.
关于java - 如何使用比较器比较空值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1682784/