Я реалізую 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 1 та Guava 2013, обидва розміщені мною - які я вважав за краще в якийсь момент часу.
Зараз я зробив чисте рішення Java 8 Лукашем Віктором прийнятою відповіддю. Це, безумовно, слід віддати перевагу, якщо на Java 8, а в наші дні Java 8 має бути доступною майже для всіх проектів.