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