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; } }