Existem em Java duas interfaces relacionadas com a comparação de objectos. A primeira, definida na package principal da linguagem, está relacionada com o conceito de ordem natural dos objectos e é, normalmente, implementada por classes cujas instâncias devem ser passíveis de comparação. A segunda interface corresponde à definição de classes para objectos que funcionam como comparadores. Neste caso, as classes não têm de ser comparáveis, já que os comparadores podem providenciar essa funcionalidade. Os comparadores surgem, por vezes, implementados como classes internas (e.g. String.CASE_INSENSITIVE_ORDER) implementando a interface pública de comparação (java.util.Comparator).
A interface Comparable<T> exige às classes que a implementam a criação de um método ( T é um tipo)
interface Comparable<T> {
int compareTo(T other);
}
Este método permite estabelecer uma ordem natural sobre objectos do tipo utilizado para parametrizar a interface. Colecções desses objectos podem então ser ordenadas utilizando métodos pré-definidos (e.g., Collections.sort ou Arrays.sort).
O método compareTo deve retornar um inteiro menor que zero, zero, ou maior que zero, caso um objecto seja "menor", igual ( equals), ou "maior" que outro objecto. Como a referência null não representa nenhum objecto, se passada como argumento, não deverá ser retornado nenhum valor, devendo as implementações lançar NullPointerException. No exemplo seguite, a ordem natural é definida pela idade do gato.
public class Cat implements Comparable<Cat> {
private int _age;
private String _name;
public Cat(int age, String name) { _age = age; _name = name; }
public int getAge() { return _age; }
public String getName() { return _name; }
public int compareTo(Cat cat) {
if (cat == null) throw new NullPointerException();
return _age - cat.getAge();
}
}
Recordar que equals deve retornar false quando é passada uma referência null como argumento.
Semelhante ao uso da interface java.lang.Comparable<T>, mas sem definir uma ordem natural para os objectos de uma classe, a interface java.util.Comparator<T> permite criar classes (implementações), cujos objectos representam funções de comparação entre dois objectos da classe utilizada como parâmetro do tipo do comparador. Os métodos exigidos pela interface Comparator são os seguintes:
interface Comparator<T> {
int compare(T um, T outro);
boolean equals(Object outro);
}
O uso é análogo ao da interface Comparable, mas não compromete uma classe com nenhuma função de comparação especial. Considerando o exemplo do gato, a definição seguinte permitiria, por exemplo, ordenar gatos por nome (String implementa Comparable<String>, definindo ordem lexicográfica).
import java.util.Comparator;
public class CatNameComparator implements Comparator<Cat> {
public int compare(Cat cat1, Cat cat2) {
return cat1.getName().compareTo(cat2.getName());
}
}
Recordar que a compatibilidade com equals e a simetria da comparação são como para o caso de compareTo (acima).
Note-se que a classe java.lang.Object já fornece uma implementação por omissão para equals, pelo que as classes podem escolher não implementar explicitamente este método, mesmo que implementem a interface Comparator.