Pessoal, tenho uma função de ordenação para ordenar minha tabela de acordo com a coluna clicada, porém a função não ordena perfeitamente, pois falha quando existem valores nulos e a ordenação não é feita da forma correta (colocando por exemplo, o 1000 antes do 2 - por ser alfanumerico a ordenação compara caractere por caractere).
Gostaria de saber se alguém possui algum código de ordenação de alfanuméricos que funcione 100%. Segue abaixo o meu código.
/**
* Ordena o vetor de clientes de acordo com a coluna no parâmetro.
* @author Ulisses Nunes
* @param numColuna - Número da coluna clicada na tabela
*/
public void ordenarTabela(int numColuna)
{
//Ordenando pelo codigo do cliente
if (numColuna == 0)
{
try {
Arrays.sort(vetor,new Comparator()
{
public int compare( Object obj1, Object obj2 )
{
Cliente cliente1 = (Cliente) obj1;
Cliente cliente2 = (Cliente) obj2;
return (cliente1.getCodigo().compareTo(cliente2.getCodigo()));
}
});
} catch (RuntimeException e) {
System.out.println(e.printStackTrace());
}
}
// Ordenando pelo nome do cliente
if (numColuna == 1)
{
try {
Arrays.sort(vetor,new Comparator()
{
public int compare( Object obj1, Object obj2 )
{
Cliente cliente1 = (Cliente) obj1;
Cliente cliente2 = (Cliente) obj2;
return (cliente1.getNome().compareToIgnoreCase(cliente2.getNome()));
}
});
} catch (RuntimeException e) {
System.out.println(e.printStackTrace());
}
}
// Ordenando pela data de nascimento do cliente
else if (numColuna == 2)
{
try {
Arrays.sort(vetor,new Comparator()
{
public int compare( Object obj1, Object obj2 )
{
Cliente cliente1 = (Cliente) obj1;
Cliente cliente2 = (Cliente) obj2;
return (cliente1.getDatnas().compareTo(cliente2.getDatnas()));
}
});
} catch (RuntimeException e) {
System.out.println(e.printStackTrace());
}
}
}
Mas e nas vezes que preciso ordenar strings alfanumericas??? por ex em endereços: Rua A, Rua 11 de Setembro, Rua C… essa é a principal duvida em questão.
Nesse caso, pelas regras da língua portuguesa, deve-se converter o número para as palavras por extenso que representam esse número, e fazer a ordenação.
Por exemplo:
“24 de Maio”, “18 de Abril”, “4 de Julho”, “14 de Fevereiro”, “25 de Março” são ordenadas como se estivessem escritas assim:
“catorze de fevereiro”
“dezoito de abril”
“quatro de julho”
“vinte e cinco de março”
“vinte e quatro de maio”
Obviamente você não deu um exemplo adequado.
Para fazer o que você quer (mas não o que você tentou explicar), é necessário então verificar se a string começa por um número; se começar, então você deve definir se as strings sem número na frente devem ficar todas depois ou todas antes das strings com números na frente. Digamos que as strings que começam por números fiquem todas antes. Então você deve escrever um método de comparação que pegue duas strings, e as separe em uma parte numérica e outra não-numérica, e comparar isso como se fossem 2 campos. OK?
import java.util.regex.*;
import java.util.*;
class OrdenacaoAlfanumerica implements Comparator<String> {
private static Pattern patStartsWithInteger = Pattern.compile ("^[0-9]+");
public int compare (String s1, String s2) {
Matcher m1 = patStartsWithInteger.matcher (s1);
Matcher m2 = patStartsWithInteger.matcher (s2);
boolean s1StartsWithInteger = m1.find();
boolean s2StartsWithInteger = m2.find();
// Regra para este método:
// Todas as strings que começam por números ficam antes. As que não começam por números ficam depois.
if (!s1StartsWithInteger && s2StartsWithInteger)
return +1; // s1 > s2
if (s1StartsWithInteger && !s2StartsWithInteger)
return -1; // s1 < s2
if (!s1StartsWithInteger && !s2StartsWithInteger)
return s1.compareTo (s2); // nenhuma começa por número, então devemos comparar como strings mesmo
// Como ambas as strings começam por números então devemos
// comparar primeiro os números, e depois as partes não numéricas.
long n1 = Long.parseLong (m1.group());
long n2 = Long.parseLong (m2.group());
if (n1 < n2) return -1; // o primeiro valor é menor que o segundo
if (n1 > n2) return +1; // o primeiro valor é maior que o segundo
return s1.compareTo (s2); // Os valores numéricos são iguais, então devemos comparar como strings mesmo
}
}
class TesteOrdenacao {
public static void main(String[] args) {
String[] teste = {
"1000 pães",
"20 biscoitos",
"Açúcar",
"007 O Espião que me amava"
};
Arrays.sort (teste, new OrdenacaoAlfanumerica ());
System.out.println (Arrays.asList (teste));
// Deve imprimir:
// [007 O Espião que me amava, 20 biscoitos, 1000 pães, Açúcar]
}
}
OK, valeu, consegui entender o funcionamento. mas tenho uma dúvida…
Imagine que tenho a classe Pessoa, que possui Identidade e que possui Nome. Desejo ordenar pelo campo nomeCompleto da classe Nome mas tenho um vetor de Pessoas. Preciso de uma função de ordenação genérica, que eu passe o campo da classe que preciso ordenar, no vetor de classes que possuo (Pessoa, Identidade, etc…)