viernes, 23 de septiembre de 2011

Comparar cadenas en Java ignorando tildes

Java
A veces es necesario comparar cadenas de texto (String) para realizar ordenaciones de elementos. Pero en esta tarea aparentemente sencilla probablemente necesitemos ignorar mayúsculas y minúsculas y las palabras con tildes en el caso del Español y si necesitamos la misma funcionalidad de ordenación en otros idiomas aún se puede complicar más ya que pueden utilizar más caracteres que pueden presentar problemas (ã, ä, å, â, æ, mapa de caracteres). Una solución que se suele aplicar habitualmente es hacer un reemplazo de esos caracteres (á, ã, ä, å, â, ...) para igualar diferentes caracteres de las cadenas (a). Pero para ello hay que conocer todos esos caracteres para cada idioma lo que puede ser un problema. Para facilitar la tarea de ordenar cadenas Java dispone de la clase Collator teniendo en cuenta ciertas reglas del idioma en concreto.

List paises = ...;
Locale locale = ...;

Collator c = Collator.getInstance(locale);
c.setStrength(Collator.PRIMARY);

Collections.sort(paises, new CollatorComparator(c));

Con una clase propia, CollatorComparator, que implementa la interfaz Comparator podemos hacer la ordenación de una lista de cadenas:

import java.util.Comparator;
import java.text.Collator;

public class CollatorComparator implements Comparator {
 
 private Collator collator;

 public CollatorComparator(Collator collator) {
  this.collator = collator;
 }

 public int compare(Object o1, Object o2) {
  return collator.compare(o1, o2);
 }

 public boolean equals(Object obj) {
  return false;
 }
}

Algo importante es la «fuerza» del comprador, que permite ajustar cuales son los caracteres que se consideran diferentes en la comparación. Disponemos de las siguientes posibilidades:
  • PRYMARY: Considera como distintos los distintos caracteres («a» vs «b»)
  • SECONDARY: Considera como distintos diferentes formas acentuadas («a» vs «á»)
  • TERTIARY: Considera como diferentes mayúsculas y minúsculas («a» vs «A»)
  • IDENTICAL: Solo se consideran idénticos («a» vs «a»)
Referencia:
java.util.Comparator
java.text.Collator
java.text.RuleBasedCollator