Utiliser un Collator pour la comparaison de chaines

Lors de la manipulation de données, il est souvent nécessaire de comparer des chaines de caractère, pour réaliser des tris par exemple. Cependant, plusieurs problèmes peuvent se poser, comme la différence de casse et la présence de lettres diacritées (possédant un accent ou une cédille, par exemple).

Si pour les problèmes de casse, il est possible de s’en sortir avec les méthodes equalsIgnoreCase() et compareToIgnoreCase() de la classe String, il n’en va pas de même pour les problèmes de diacritiques. En effet, non seulement il est très difficile de prévoir tous les cas, mais en plus ce problème est dépendant de la langue utilisée (alors qu’il y a moins de 20 mots comportant des diacritiques en anglais, la quasi-totalité des mots vietnamiens en comportent).

Heureusement, Java propose un outil nommé Collator (du verbe anglais “to collate”, ordonner, ranger, vérifier l’ordre) permettant de gérer ce problème de façon simple. En effet, le Collator permet de faire une comparaison intelligente en tenant compte de la locale, mais aussi des diacritiques et de la casse.

Voici un petit exemple pour illustrer son fonctionnement :

[pastacode lang=”java” message=”” highlight=”” provider=”manual”]

package com.viaxoft.test.collator;import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;public class TestCollator {
public static void main (String [] args) {
final List pays = new ArrayList ();
pays.add("zimbabwe");
pays.add("angola");
pays.add("Australie");
pays.add("Zambie");
pays.add("éthiopie");
pays.add("États-Unis");
pays.add("Égypte");
pays.add("Sénégal");
pays.add("Serbie");Collections.sort(pays);
printTitle("Tri par défaut");
printList(pays);
Collections.sort(pays, new Comparator () {
public int compare(String o1, String o2) {
return o1.compareToIgnoreCase(o2);
}
});
printTitle("Tri en ignorant la casse");
printList(pays);

final Collator frCollator = Collator.getInstance(Locale.FRENCH);
Collections.sort(pays, new Comparator () {
public int compare(String o1, String o2) {
return frCollator.compare(o1, o2);
}
});
printTitle("Tri avec un Collator");
printList(pays);

frCollator.setStrength(Collator.TERTIARY);
printTitle("Comparaison avec un Collator "TERTIARY"");
compareWithCollator ("egypte", "egypte", frCollator);
compareWithCollator ("Egypte", "egypte", frCollator);
compareWithCollator ("égypte", "egypte", frCollator);
compareWithCollator ("Égypte", "egypte", frCollator);
compareWithCollator ("Égypte", "Sénégal", frCollator);

frCollator.setStrength(Collator.SECONDARY);
printTitle("Comparaison avec un Collator "SECONDARY"");
compareWithCollator ("egypte", "egypte", frCollator);
compareWithCollator ("Egypte", "egypte", frCollator);
compareWithCollator ("égypte", "egypte", frCollator);
compareWithCollator ("Égypte", "egypte", frCollator);
compareWithCollator ("Égypte", "Sénégal", frCollator);

frCollator.setStrength(Collator.PRIMARY);
printTitle("Comparaison avec un Collator "PRIMARY"");
compareWithCollator ("egypte", "egypte", frCollator);
compareWithCollator ("Egypte", "egypte", frCollator);
compareWithCollator ("égypte", "egypte", frCollator);
compareWithCollator ("Égypte", "egypte", frCollator);
compareWithCollator ("Égypte", "Sénégal", frCollator);
}

private static void printTitle (final String title) {
System.out.println("");
System.out.println(title);
System.out.println(title.replaceAll(".", "-"));
}

private static void printList (final List list) {
int i=1;
for (String str : list) {
System.out.println(i+". "+str);
i++;
}
}

private static void compareWithCollator (final String str1, final String str2, final Collator collator) {
if (collator.equals(str1, str2))
System.out.println(str1+"=="+str2);
else
System.out.println(str1+"!="+str2);
}
}

[/pastacode]

 

Et le résultat de l’exécution de ce programme :

Tri par défaut

  1. Australie
  2. Serbie
  3. Sénégal
  4. Zambie
  5. angola
  6. zimbabwe
  7. Égypte
  8. États-Unis
  9. éthiopie

Tri en ignorant la casse

  1. angola
  2. Australie
  3. Serbie
  4. Sénégal
  5. Zambie
  6. zimbabwe
  7. Égypte
  8. États-Unis
  9. éthiopie

Tri avec un Collator

  1. angola
  2. Australie
  3. Égypte
  4. États-Unis
  5. éthiopie
  6. Sénégal
  7. Serbie
  8. Zambie
  9. zimbabwe

Comparaison avec un Collator “TERTIARY”
egypte==egypte
Egypte!=egypte
égypte!=egypte
Égypte!=egypte
Égypte!=Sénégal

Comparaison avec un Collator “SECONDARY”
egypte==egypte
Egypte==egypte
égypte!=egypte
Égypte!=egypte
Égypte!=Sénégal

Comparaison avec un Collator “PRIMARY”
egypte==egypte
Egypte==egypte
égypte==egypte
Égypte==egypte
Égypte!=Sénégal

Comme on s’y attendait, la liste des pays n’est pas triée correctement avec les comparateurs de base de la classe String, mais l’est avec le Collator.
Cet exemple montre également l’influence de la propriété “strength” (force, puissance en anglais) sur le test d’égalité du collator : en “TERTIARY”, on tient compte de la casse et des diacritiques, en “SECONDARY” seulement des diacritiques, et en “PRIMARY” ni de l’un ni de l’autre. Il faudra donc également prendre en compte ce paramètre lors de l’utilisation d’un Collator, et le choisir en fonction du besoin.