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