ABC sort
Tato třída implementuje rozhraní java.util.Comparator<T> pro porovnávání dvou řetězců. Porovnává dva řetězce dle pravidel českého pravopisu. Tento algoritmus je dle normy (ČSN 97 6030) z roku 1994 dvouprůchodový, podrobnosti se dozvíte v normě.
Když se vám algoritmus podaří ještě o něco zrychlit, budu vám vděčen, když mě dáte vědět.
Použití:List<String> vektor = new ArrayList<String> ();Collections.sort( vektor, AbcComparator.getInstance() );
Pozn: Můžete také využít třídu java.text.Collator: Collections.sort( vektor, Collator.getInstance( new Locale("cs_CZ") ) );, ale moje třída je dle testů několikrát rychlejší...
class AbcComparator implements Comparator<String> {
private static final char[] translateTableFrom = {'á','ä','ď','é','ě','ë','í','ň','ó','ö','š','ß','ť','ú','ů','ü','ý','ÿ'};
private static final char[] translateTableTo = {'a','a','d','e','e','e','i','n','o','o','s','s','t','u','u','u','y','y'};
private static final String abcFirst = "abcčdefghijklmnopqrřsštuvwxyzž0123456789";
private static final String abcSecond = "aáäbcčdďeéěëfghiíjklmnňoóöpqrřsšßtťuúůüvwxyýÿzž0123456789";
private static final int chF = 9, chS = 15; // pozice pismena ch v 1. a 2. abecede
private static final AbcComparator instance = new AbcComparator();
private AbcComparator() {}
public static final AbcComparator getInstance() {
return instance;
}
public int compare(String str1, String str2) {
int res = comp(str1, str2, abcFirst, chF);
return (res == 0) ? comp(str1, str2, abcSecond, chS) : res;
}
private int comp(String str1, String str2, String abc, int ch) {
int len1 = str1.length();
int len2 = str2.length();
for (int i = 0; i < len1; i++) {
if (i >= len2) break;
char a = Character.toLowerCase(str1.charAt(i));
char b = Character.toLowerCase(str2.charAt(i));
// ch v 1. stringu?
if ( (a == 'c') && (i < (len1 - 1)) && (Character.toLowerCase(str1.charAt(i + 1)) == 'h')) {
if (b == 'c') {
if ( (i < (len2 - 1)) && (Character.toLowerCase(str2.charAt(i + 1)) == 'h')) {
continue;
}
return 1;
}
int pos2 = abc.indexOf(b);
pos2 = (pos2 < 0) ? abc.indexOf(toChar(b)) : pos2; // konverze pri prvnim pruchodu
return (pos2 < ch) ? 1 : -1;
}
// ch v 2. stringu?
if ( (b == 'c') && (i < (len2 - 1)) && (Character.toLowerCase(str2.charAt(i + 1)) == 'h')) {
int pos1 = abc.indexOf(a);
pos1 = (pos1 < 0) ? abc.indexOf(toChar(a)) : pos1; // konverze pri prvnim pruchodu
return (pos1 < ch) ? -1 : 1;
}
int pos1 = abc.indexOf(a);
int pos2 = abc.indexOf(b);
pos1 = (pos1 < 0) ? abc.indexOf(toChar(a)) : pos1; // konverze pri prvnim pruchodu
pos2 = (pos2 < 0) ? abc.indexOf(toChar(b)) : pos2; // konverze pri prvnim pruchodu
if (pos1 != pos2) return (pos1 < pos2) ? -1 : 1;
}
return (len1 < len2) ? -1 : ( (len1 > len2) ? 1 : 0);
}
private char toChar(char c) {
for(int i = 0; i < translateTableFrom.length; i++) {
if(c == translateTableFrom[i]) return translateTableTo[i];
}
// System.out.println("chyba: " + c);
return c;
}
}