1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
| /**
* Comparaison de chaine de caractère qui prend en compte la valeur des sections numériques...
*
* @author adiGuba
*/
class NaturalStringComparator implements Comparator<String> {
/** Le comparateur qui sera utilisé pour comparer les chaines */
private final Comparator<? super String> stringCompare;
/**
* Comparaison des chaines par défaut (avec compareTo()).
*/
public NaturalStringComparator() {
this(null);
}
/**
* Comparaison des chaines selon un comparateur spécifique.
*/
public NaturalStringComparator(Comparator<? super String> comparator) {
this.stringCompare = comparator;
}
/**
* Retourne l'index du prochain caractère d'un certain type.
* @param str La chaine à lire
* @param start Index de départ de la recherche
* @param noDigit : true pour rechercher n'importe quel caractètre qui ne soit pas un chiffre
*/
private int indexOf(String str, int start, boolean noDigit) {
if (start>=0) {
final int LEN = str.length();
for (int i=start; i<LEN; i++) {
if (Character.isDigit(str.charAt(i))^noDigit) {
return i;
}
}
}
return -1;
}
/**
* Retourne la valeur entière entre deux emplacements de la chaine
* @param str La chaine à lire
* @param start Début de la valeur entière
* @param end Fin de la valeur entière
* @return La valeur entière correspondante
*/
private int valueOf(String str, int start, int end) {
if (end>=0) {
return Integer.valueOf(str.substring(start, end));
}
return Integer.valueOf(str.substring(start));
}
/**
* Effectue une comparaison de chaine selon le comparateur fourni
*/
private int stringCompare(String o1, String o2) {
if (this.stringCompare!=null) {
return this.stringCompare.compare(o1, o2);
}
return o1.compareTo(o2);
}
/**
* Comparaison des chaines en prenant en compte la valeur des nombres.
*/
@Override
public int compare(String o1, String o2) {
final int defaultResult = stringCompare(o1, o2);
if (defaultResult!=0) {
// Si les chaines sont différentes :
int start1 = 0;
int start2 = 0;
int end1 = 0;
int end2 = 0;
// On récupère les index des prochains chiffres
int idx1 = indexOf(o1, start1, false);
int idx2 = indexOf(o2, start2, false);
// Tant qu'on a bien un chiffre de chaque coté :
while (idx1>=0 && idx2>=0) {
// On compare les chaines avant les chiffres :
int result = stringCompare(o1.substring(start1,idx1), o2.substring(start2,idx2));
if (result!=0) {
// Si on trouve une différence, on peut déjà s'arrêter :
return result;
}
// On récupère l'index du caractères suivant :
end1 = indexOf(o1, idx1, true);
end2 = indexOf(o2, idx2, true);
// On récupère la valeur entière du chiffre trouvé :
int value1 = valueOf(o1, idx1, end1);
int value2 = valueOf(o2, idx2, end2);
// Si on trouve une différence on la prend en compte :
if (value1<value2) {
return -1; // value1 plus petit que value2
} else if (value1>value2) {
return 1; // value1 plus grand que value2
}
// En on continue sur les mêmes index :
start1 = end1;
start2 = end2;
// On récupère les index des nombres
idx1 = indexOf(o1, start1, false);
idx2 = indexOf(o2, start2, false);
}
}
// On n'a trouvé aucune différence dans les chiffres :
return defaultResult;
}
} |
Partager