Я реализую метод 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: Эдди справа; исправлено, что "оба названия имеют нулевой" случай выше
О принятом ответе
Я задал этот вопрос еще в 2009 году, на Java 1.6, конечно, и в то время чистое решение JDK от Eddie было моим предпочтительный принятый ответ. Я так и не смог изменить это до сих пор (2017 год).
Существуют также сторонние библиотечные решения - в 2009 году Apache Commons Collections один и один из двух выпусков Guava в 2013 году, которые я опубликовал, - что я действительно предпочитал в какой-то момент время.
Теперь я сделал чистый Java 8 решение от Lukasz Wiktor принятый ответ. Это должно быть особенно предпочтительным, если на Java 8, и в наши дни Java 8 должен быть доступен почти для всех проектов.