Я реализую 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. было моим предпочтительным принятым ответом. Я никогда не удосужился изменить это до сих пор (2017).
Есть также сторонние библиотечные решения - Apache Commons Collections один 2009 года и Guava 2013 года, оба опубликованные мной, - которые я предпочел в какой-то момент времени.
Я теперь сделал чистое решение Java 8 от Лукаша Виктора принятым ответом. Это определенно должно быть предпочтительным, если на Java 8, и в настоящее время Java 8 должна быть доступна почти для всех проектов.