Estou implementando o compareTo()
método para uma classe simples como esta (para poder usar Collections.sort()
e outros brindes oferecidos pela plataforma Java):
public class Metadata implements Comparable<Metadata> {
private String name;
private String value;
// Imagine basic constructor and accessors here
// Irrelevant parts omitted
}
Quero que a ordem natural desses objetos seja: 1) classificada por nome e 2) classificada por valor, se o nome for o mesmo; ambas as comparações não diferenciam maiúsculas de minúsculas. Para ambos os campos, os valores nulos são perfeitamente aceitáveis, portanto, compareTo
não devem ser interrompidos nesses casos.
A solução que vem à mente é a seguinte: (estou usando "cláusulas de guarda" aqui, enquanto outros podem preferir um único ponto de retorno, mas isso não vem ao caso):
// 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);
}
Isso faz o trabalho, mas não estou perfeitamente feliz com esse código. É certo que não é muito complexo, mas é bastante detalhado e tedioso.
A questão é: como você tornaria isso menos detalhado (mantendo a funcionalidade)? Sinta-se à vontade para consultar as bibliotecas padrão Java ou o Apache Commons, se elas ajudarem. A única opção para tornar isso (um pouco) mais simples seria implementar meu próprio "NullSafeStringComparator" e aplicá-lo para comparar os dois campos?
Edições 1-3 : Eddie está certo; Corrigido o caso "ambos os nomes são nulos" acima
Sobre a resposta aceita
Eu fiz essa pergunta em 2009, no Java 1.6, é claro, e na época a solução JDK pura de Eddie era minha resposta preferida aceita. Eu nunca mudei para mudar isso até agora (2017).
Também existem soluções de bibliotecas de terceiros - uma das coleções Apache Commons 2009 e uma da Guava 2013, ambas postadas por mim - que eu preferia em algum momento.
Agora fiz a solução Java 8 limpa por Lukasz Wiktor a resposta aceita. Definitivamente, isso deve ser preferido no Java 8, e atualmente o Java 8 deve estar disponível para quase todos os projetos.