Ordenação de Strings

maxresdefault (1).jpg

Ao tentar ordenar um ArrayList de objetos por um campo do tipo String, percebi que os textos acentuados não eram corretamente ordenados. A explicação para este fato é o seguinte: na linguagem Java, a ordenação de um texto varia de acordo com o Locale (idioma).

Como o default do Locale é o idioma inglês, onde quase nenhum caractere acentuado existe, as letras acentuadas não são equiparados às respectivas letras sem acento. Desta maneira, como caracteres acentuados têm códigos numéricos superiores aos sem acento, acabam indo parar no final da listagem ordenada.

Para demonstrar a solução deste problema, segue abaixo código fonte que ordena listagem de clientes pelo nome.

A classe Cliente possui os atributos privados codigo e nome, além de seus respectivos métodos de acesso. Ela implementa a interface Comparable sobrescrevendo o metodo compareTo que realiza a ordenação comparando o atributo nome de duas instâncias da classe Cliente.

import java.text.Collator;
import java.util.Locale;

public class Cliente implements Comparable {

        private Integer codigo;

	private String nome;

 	public Cliente(Integer codigo, String nome) {
 		this.codigo = codigo;
 		this.nome = nome;
 	}

 	public Integer getCodigo() {
 		return codigo;
 	}

	public void setCodigo(Integer codigo) {
 		this.codigo = codigo;
 	}

 	public String getNome() {
 		return nome;
 	}

 	public void setNome(String nome) {
 		this.nome = nome;
 	}

 	@Override
 	public String toString() {
 		return this.codigo + " - " + this.nome;
 	}

	@Override
 	public int compareTo(Cliente cliente) {
 		if (cliente != null) {
 			return this.getNome().compareTo(cliente.getNome());
 		} else {
 			return 0;
 		}
 	}

}

A classe OrdenacaoCliente cria uma lista de clientes com nome diversos e a exibe primeiramente desordenada. Depois o metodo sort da classe Collections ordena o ArrayList de clientes pelo nome.

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class OrdenacaoCliente {

	public static void main(String[] args) {

		List clientes = new ArrayList();

 		clientes.add(new Cliente(1, "Cristiano Ronaldo"));
 		clientes.add(new Cliente(2, "Fernanda Vasconcelos"));
 		clientes.add(new Cliente(3, "Ângela Souza"));
 		clientes.add(new Cliente(4, "Débora Marinho"));
 		clientes.add(new Cliente(5, "Bruno Garcia"));
 		clientes.add(new Cliente(6, "Érika Eleniak"));

 		System.out.println("Lista desordenada:\n" + clientes);

 		Collections.sort(clientes);

 		System.out.println("Lista ordenada:\n" + clientes);
 	}
}

O resultado impresso no console depois da execução é o seguinte:

Lista desordenada:
[1 - Cristiano Ronaldo, 2 - Fernanda Vasconcelos, 3 - Ângela Souza, 4 - Débora Marinho, 5 - Bruno Garcia, 6 - Érika Eleniak]

Lista ordenada:
[5 - Bruno Garcia, 1 - Cristiano Ronaldo, 4 - Débora Marinho, 2 - Fernanda Vasconcelos, 3 - Ângela Souza, 6 - Érika Eleniak]

Nota-se que os nomes que começam com letras acentuadas vão para o final da listagem. A solução para ordenar corretamente a listagem é instanciar a classe Collator definindo o Locale para o idioma português e usar o seu método compare ao invés do compareTo da classe String.

     @Override
     public int compareTo(Cliente cliente) {
	     Collator cot = Collator.getInstance(new Locale("pt", "BR"));
	     if (cliente != null) {
	          return cot.compare(this.getNome(), cliente.getNome());
             } else {
	          return 0;
	     }
     }

Depois da alteração, a ordenação é realizada corretamente:

Lista desordenada:
[1 - Cristiano Ronaldo, 2 - Fernanda Vasconcelos, 3 - Ângela Souza, 4 - Débora Marinho, 5 - Bruno Garcia, 6 - Érika Eleniak]

Lista ordenada:
[3 - Ângela Souza, 5 - Bruno Garcia, 1 - Cristiano Ronaldo, 4 - Débora Marinho, 6 - Érika Eleniak, 2 - Fernanda Vasconcelos]

11 comentários

  1. Comigo deu erro aqui, mas funcionou quando na linha 4 coloquei:

    public class Cliente implements Comparable {

    em vez de:

    public class Cliente implements Comparable {

    Curtir

  2. Caramba, me deparei com esse problema, e fiz todo um malabarismo usando regex pra resolver esse problema, agora vou tirar o que fiz e fazer como mostrado nesse post.

    muito bom.

    Curtir

Deixe uma resposta