É o que o armando falou, então! O lance está no uso da interface Comparable e, adicionando ao que o armando sugeriu, também no uso da interface Comparator.
[size=20][color=blue]java.lang.Comparable[/color][/size]
Quando uma classe implementa a interface java.lang.Comparable, ela deve implementar o método compareTo desta interface. Veja aqui a interface Comparable:
package java.lang;
public interface Comparable<T> {
public int compareTo(T o);
}
Este método compareTo recebe um parâmetro do tipo T e retorna um int. A idéia deste método é estabelecer uma ordenação natural entre objetos do tipo da classe que implementa a interface e objetos do tipo T(Geralmente este T é a mesma classe que implementa Comparable). Trocando em miúdos, o intuito é fazer uma comparação entre o objeto que invoca o método compareTo(chamemo-o de este objeto) e o objeto que foi passado por parâmetro(chamemo-o de objeto passado. O int retornado por esse método vai depender desta comparação, da seguinte forma:
:arrow: Se este objeto for considerado “menor” que o objeto passado, retorna-se um inteiro negativo;
:arrow: Se este objeto for considerado “maior” que o objeto passado, retorna-se um inteiro positivo;
:arrow: Se este objeto for considerado “igual” ao objeto passado, retorna-se zero.
O que definine se este objeto é maior ou menor ou igual ao objeto passado é a forma como você implementa este método na sua classe que “deu” implements em Comparable.
Por exemplo, suponha que temos uma classe chamada cliente, que armazena o nome, o cpf e o código do cliente. Suponha agora que dejamos que a ordenação natural dos clientes seja dada pelo código. Ou seja, um cliente com código 738 é “maior” que um cliente com código 451.
O código abaixo mostra como faríamos esta classe obedecer este critério de ordenação utilizando a implementação da interface Comparable:
public class Cliente implements Comparable<Cliente>{
private int code;
private String name;
private String cpf;
//Contrutores, getters e setters
public String toString() {
return code + " - " + name + " - " + cpf;
}
public int compareTo(Cliente other) {
return this.code - other.code;
}
}
Note que o T neste caso é a classe Cliente, o que faz com que os objetos da classe Cliente sejam naturalmente comparáveis a outros objetos do tipo Cliente.
No corpo do método compareTo, definimos o critério para a ordenação. Neste caso, temos o seguinte:
:arrow: Se o campo code deste objeto for menor que o mesmo campo do objeto passado, então retorna-se um número estritamente negativo, indicando que este objeto é “menor” que o objeto passado
:arrow: Se o campo code deste objeto for maior que o mesmo campo do objeto passado, então retorna-se um número estritamente positivo, indicando que este objeto é “maior” que o objeto passado
:arrow: Se o campo code deste objeto for igual ao mesmo campo do objeto passado, então retorna-se o número zero, indicando que este objeto é “igual” ao objeto passado
Veja que o critério depende unica e exclusivamente da vontade do programador (Ou da de que o está pagando… :lol: ). Se quisessemos, por exemplo, definir a ordenação dos objetos Cliente baseada no valor do campo cpf, bastaria implementar o método compareTo de outra maneira:
public int compareTo(Cliente other) {
return this.cpf.compareTo(other.cpf);
}
Note que o campo cpf é um objeto do tipo String e que estamos invocando, coincidentemente, um método chamado compareTo a partir do campo cpf deste objeto e passando por parâmetro o campo cpf do objeto passado. Fizemos isso porque a classe String também implementa a interface Comparable, provendo uma ordenação alfabética entre os objetos String.
Utilize a seguinte classe para testar a classe cliente e a comparação entre seus objetos:
class TesteCliente{
public static void main(String[] args) {
Cliente cliente01 = new Cliente(1528, "Luciano Mantuaneli", "528966582-96");
Cliente cliente02 = new Cliente(52, "Antonin Dvorak", "000002526-01");
Cliente cliente03 = new Cliente(8755, "Anuia Okele", "841575552-00");
comparaClientes(cliente01, cliente02, cliente03);
System.out.println();
comparaClientes(cliente02, cliente01, cliente03);
System.out.println();
comparaClientes(cliente03, cliente01, cliente02);
System.out.println();
}
public static void comparaClientes(Cliente ... clientes) {
Cliente pivot = clientes[0];
System.out.println("Cliente " + pivot.getName());
for(int i = 1; i < clientes.length; i++) {
if(pivot.compareTo(clientes[i]) > 0)
System.out.println("\tÉ maior que o cliente " + clientes[i].getName());
else if(pivot.compareTo(clientes[i]) < 0)
System.out.println("\tÉ menor que o cliente " + clientes[i].getName());
else//(pivot.compareTo(clientes[i]) == 0)
System.out.println("\tÉ igual ao cliente " + clientes[i].getName());
}
}
}
[size=20][color=blue]java.util.Comparator[/color][/size]
A interface comparator é muito parecida com a Comparable. Perceba a diferença no significado dos nomes:
:arrow: Comparable: Em português significa “comparável”. Ou seja, um objeto de uma classe que implementa a interface Comparable, é um objeto comparável, um objeto que pode se comparar com outro objeto de uma classe T.
:arrow: Comparator: Em português significa “comparador”. Ou seja, um objeto de uma classe que implementa a interface Comparator, é um objeto capaz de comparar outros dois objetos de uma classe T entre si.
Percebe a sutileza? Um objetod de uma classe Comparator (uma classe que implemente a interface Comparator) é apenas um intermediador no processo de ordenação entre dois objetos do tipo T.
Veja aqui a interface java.util.Comparator
public interface Comparator<T> {
int compare(T o1, T o2);
boolean equals(Object obj);
}
Não vou entrar no mérito da utilidade do método equals para um Comparator, mas vale a pena você dar uma pesquisada depois.
Note que o método compare da Comparator é muito semelhante ao compareTo da Comparable. A diferença, além do nome, é a presença de mais um parâmetro do tipo T. Isto faz muito sentido depois de termos discutido a diferença de significado entre Comparator e Comparable: o1 e o2 são os objetos do tipo T que serão comparados entre si pelo objeto da classe que implementa Comparator. A regra para o retorno deste método é também muito parecida com a do método homônimo de Comparable, bastando apenas você tratar o1 como se fosse o “este objeto” e o2 como se fosse o “objeto passado”.
Voltando ao exemplo anterior, a classe Cliente já tem definida uma ordenação natural, mas, e se quisermos comparar objetos do tipo Cliente segundo outros critérios, como por exemplo, o nome do cliente? É aí que entre um objeto Comparator para nos auxiliar.
O código a seguir mostra uma classe que implementa Comparator e provê a ordenação de objetos Cliente segundo a ordem alfabética do campo nome:
import java.util.Comparator;
public class ComparadorClientePorNome implements Comparator<Cliente> {
public int compare(Cliente cli1, Cliente cli2) {
return cli1.getName().compareTo(cli2.getName());
}
}
Para testar, utilize a classe a seguir e veja como se comporta um objeto da classe ComparadorClientePorNome:
[code]
class TesteComparadorClientePorNome{
private static ComparadorClientePorNome comparador =
new ComparadorClientePorNome();
public static void main(String[] args) {
Cliente cliente01 = new Cliente(1528, "Luciano Mantuaneli", "528966582-96");
Cliente cliente02 = new Cliente(52, "Antonin Dvorak", "000002526-01");
Cliente cliente03 = new Cliente(8755, "Anuia Okele", "841575552-00");
comparaClientesPorNome(cliente01, cliente02, cliente03);
System.out.println();
comparaClientesPorNome(cliente02, cliente01, cliente03);
System.out.println();
comparaClientesPorNome(cliente03, cliente01, cliente02);
System.out.println();
}
private static void comparaClientesPorNome(Cliente ... clientes) {
Cliente pivot = clientes[0];
System.out.println(
"Segundo o critério definido pelo Comparator " +
"\"ComparadorClientePorNome\", o Cliente " + pivot.getName()
);
for(int i = 1; i < clientes.length; i++) {
if(comparador.compare(pivot, clientes[i]) > 0)
System.out.println("\tÉ maior que o cliente " + clientes[i].getName());
else if(comparador.compare(pivot, clientes[i]) < 0)
System.out.println("\tÉ menor que o cliente " + clientes[i].getName());
else//(comparador.compare(pivot, clientes[i]) == 0)
System.out.println("\tÉ igual ao cliente " + clientes[i].getName());
}
}
}[/code]
Note que agora a tarefa de comparação é realizada pelo objeto comparador, e não mais por um dos objetos Cliente comparados.
A utilidade de um Comparator é poder estabelecer uma ordenação diversa àquela naturalmente definida por um objeto Comparable. É também útil quando queremos ordenar algum objeto que não é Comparable, ou seja, que não tem definida uma ordenação natural.
[size=20][color=blue]Ordenando um List[/color][/size]
Existe no pacote java.util uma classe auxiliar (Só com métodos estáticos) chamada Collections que traz, entre outros, um método chamado sort. Este método recebe um objeto de alguma classe que implemente List<T extends Comparable<? super T>>. Resumindo essa papagaiada, recebe alguma lista de objetos, os quais devem por sua vez serem objetos Comparable.
Como a classe Collection força que os elementos da lista passada para o método sort sejam objetos Comparable, ela “sabe” que eles têm um método chamado compareTo, e então reorganiza a lista de acordo com a comparação entre os elementes através dos seus compareTo.
A classe Collection disponibiliza ainda uma sobrecarga do método sort que recebe por parâmetro um objeto que implemente List e um objeto que implemente Comparator<? super T>. Ou seja, recebe uma lista de elementos do tipo T, juntamente com o comparador capaz de comparar entre si objetos do tipo - ou compatíveis - T. Esta versão do método sort aplica os elementos do List ao método compare do Comparator para realizar a ordenação. Importante: Se os elementos da lista forem objetos cuja classe implementa Comparable, e utilizarmos esta versão do sort, a ordenação obedecerá os critérios estabelecidos pelo objeto Comparator, e não os critérios definidos pela classe dos objetos Comparable.
A seguinte classe monta um ArrayList (Que é uma classe que implementa a interface List) de objetos Cliente e a ordena com os métodos sort da classe Collection:
import java.util.ArrayList;
import java.util.Collections;
class TesteListDeClientes{
public static void main(String[] args) {
ArrayList<Cliente> clientes = new ArrayList<Cliente>();
clientes.add(new Cliente(1528, "Luciano Mantuaneli", "528966582-96"));
clientes.add(new Cliente(52, "Antonin Dvorak", "000002526-01"));
clientes.add(new Cliente(8755, "Anuia Okele", "841575552-00"));
System.out.println("LISTA ORIGINAL\n==============");
for (Cliente cliente : clientes) {
System.out.println(cliente);
}
System.out.println();
System.out.println(
"LISTA ORDENADA POR CÓDIGO \n" +
"Ordem natural definida pelos próprios objetos Cliente,\n" +
"através da implementação da interface Comparable\n" +
"======================================================"
);
Collections.sort(clientes);
for (Cliente cliente : clientes) {
System.out.println(cliente);
}
System.out.println();
System.out.println(
"LISTA ORDENADA POR NOME \n" +
"Ordem definida por um objeto da classe \"ComparadorClientePorNome\",\n" +
"a qual implementa a interface Comparator\n" +
"===================================================================="
);
Collections.sort(clientes, new ComparadorClientePorNome());
for (Cliente cliente : clientes) {
System.out.println(cliente);
}
}
}
[size=20][color=blue]Ordenando um vetor[/color][/size]
Para ordenor um vetor, utilizamos o mesmo “esquema” para ordenar um List. As diferenças estão na classe utilitária, que agora é a classe java.util.Arrays, e os métodos sort, que são
:arrow: sort(Object[])
:arrow: sort(T[] a, Comparator<? super T> c)
A classe abaixo faz um teste com um vetor de objetos Cliente. Na verdade, é o mesmo teste anterior, aquele com o List. Portanto, a saída deste teste será idêntica a do teste anterior:
import java.util.Arrays;
class TesteVetorDeClientes{
public static void main(String[] args) {
Cliente[] clientes = {
new Cliente(1528, "Luciano Mantuaneli", "528966582-96"),
new Cliente(52, "Antonin Dvorak", "000002526-01"),
new Cliente(8755, "Anuia Okele", "841575552-00")
};
System.out.println("LISTA ORIGINAL\n==============");
for (Cliente cliente : clientes) {
System.out.println(cliente);
}
System.out.println();
System.out.println(
"LISTA ORDENADA POR CÓDIGO \n" +
"Ordem natural definida pelos próprios objetos Cliente,\n" +
"através da implementação da interface Comparable\n" +
"======================================================"
);
Arrays.sort(clientes);
for (Cliente cliente : clientes) {
System.out.println(cliente);
}
System.out.println();
System.out.println(
"LISTA ORDENADA POR NOME \n" +
"Ordem definida por um objeto da classe \"ComparadorClientePorNome\",\n" +
"a qual implementa a interface Comparator\n" +
"===================================================================="
);
Arrays.sort(clientes, new ComparadorClientePorNome());
for (Cliente cliente : clientes) {
System.out.println(cliente);
}
}
}
Agora, tente aplicar esses conceitos no seu caso. Qualquer dúvida, poste mais.
Divirta-se!