2013-03-20 7 views
5

Chciałem wydrukować posortowane polskie nazwy wszystkich dostępnych języków.Sortowanie ciągów o nie-zachodnich znakach

import java.util.*; 

public class Tmp 
{ 
    public static void main(String... args) 
    { 
    Locale.setDefault(new Locale("pl","PL")); 
    Locale[] locales = Locale.getAvailableLocales(); 
    ArrayList<String> langs = new ArrayList<String>(); 
    for(Locale loc: locales) { 
     String lng = loc.getDisplayLanguage(); 
     if(!lng.trim().equals("") && ! langs.contains(lng)){ 
     langs.add(lng); 
     } 
    } 
    Collections.sort(langs); 
    for(String str: langs){ 
     System.out.println(str); 
    } 
    } 
} 

Niestety mam problem z sortowaniem. Wyjście jest:

: 
: 
kataloński 
koreański 
litewski 
macedoński 
: 
: 
węgierski 
włoski 
łotewski 

Niestety w polskim ł przychodzi po l i przed m więc wyjście powinno być:

: 
: 
kataloński 
koreański 
litewski 
łotewski 
macedoński 
: 
: 
węgierski 
włoski 

Jak można tego dokonać? Czy istnieje uniwersalna metoda zależna od języka (powiedz, że teraz chcę to wyświetlić i posortować w innym języku z innymi regułami sortowania).

+1

Czy sprawdziłeś to rozwiązanie? http://stackoverflow.com/questions/12889760/sort-list-of-strings-with-localization – Abdul

Odpowiedz

4

Należy zdać Collator metody sortowania:

// sort according to default locale 
Collections.sort(langs, Collator.getInstance()); 

Domyślny porządek jest określony przez codepoints Unicode w ciąg, a to nie jest prawidłowa kolejność alfabetyczna w dowolnym języku.

2

Spójrz na java.text.Collator.newInstance(Locale). Musisz podać polskie locale w twoim przypadku. Kolektory implementują interfejs Comparator, dzięki czemu można go używać w interfejsach API sortowania oraz w posortowanych strukturach danych, takich jak TreeSet.

6

spróbować

Collections.sort(langs, Collator.getInstance(new Locale("pl", "PL"))); 

będzie produkować

... 
litewski 
łotewski 
... 

zobaczyć Kol Lator API dla szczegółów

0

Mam do czynienia z tym samym problemem. Zauważyłem, że lokalne rozwiązanie dla kolektora działa dobrze dla Androida 7.0, ale nie działa na wcześniejszych wersjach Androida. Mam zaimplementowany następujący algorytm. Jest dość szybki (sortuję ponad 3000 ciągów) i działa też na wcześniejszych wersjach Androida.

public class SortBasedOnName implements Comparator { 

    private Map<Character, Integer> myCharMap; 
    private final static Map<Character, Integer>myPolCharTable = new HashMap<Character, Integer>(); 
    static { 
     myPolCharTable.put(' ',0x0020); 
     myPolCharTable.put('!',0x0021); 
     myPolCharTable.put('"',0x0022); 


     myPolCharTable.put('a',0x0040); 
     myPolCharTable.put('ą',0x0041); 
     myPolCharTable.put('b',0x0042); 
     myPolCharTable.put('c',0x0043); 
     myPolCharTable.put('ć',0x0044); 


     myPolCharTable.put('{',0x0066); 
     myPolCharTable.put('|',0x0067); 
     myPolCharTable.put('}',0x0068); 
    } 

    public SortBasedOnName() {} 

    public int compare(Object o1, Object o2) { 

     Dictionary dd1 = (Dictionary) o1; 
     Dictionary dd2 = (Dictionary) o2; 

    return strCompareWithDiacritics(dd1.getOriginal(), dd2.getOriginal()); 
    } 

    private int strCompareWithDiacritics(String s1, String s2) { 

     int i = 0; 
     int result = 0; 
     int length =0; 

     s1 = s1.toLowerCase(); 
     s2 = s2.toLowerCase(); 
     if (s1.length() > s2.length()) { 
      result = 1; 
      length = s2.length(); 
     } else if (s1.length() < s2.length()) { 
      result = -1; 
      length = s1.length(); 
     } else if (s1.length() == s2.length()) { 
      result = 0; 
      length = s1.length(); 
     } 

     try { 
      while (i <length) { 
       if (myPolCharTable.get(s1.charAt(i)) > myPolCharTable.get(s2.charAt(i))) { 
        result = 1; 
        break; 
       } else if (myPolCharTable.get(s1.charAt(i)) < myPolCharTable.get(s2.charAt(i))) { 
        result = -1; 
        break; 
       } 
       i++; 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     return result; 
    } 
}