Сопоставление Java игнорирует пространство
Недавно я понял, что Java Collation, похоже, игнорирует пробелы.
У меня есть список следующих терминов:
Amman Jost
Ammann Heinrich
Ammanner Josef
Bär Walter
Bare Werner
Barr Burt
Barraud Maurice
Приведенный выше порядок отражает желаемый порядок для Германии, т.е. занимает пространство в счет.
Однако Java Collation с использованием
Collator collator = Collator.getInstance(Locale.GERMANY);
Collections.sort(values, collator);
дает мне следующий порядок:
Amman Jost
Ammanner Josef
Ammann Heinrich
Bare Werner
Barraud Maurice
Barr Burt
Bär Walter
Результат выше не является тем, что я ожидал, поскольку пространства не учитываются (выглядит так, как описано здесь: Википедия Алфавитный порядок).
Означает ли это, что Java Collation не используется для такого использования или я что-то не так здесь делаю? Есть ли способ сделать пространство Java Collation осведомленным?
Буду рад за любые комментарии или рекомендации.
Ответы
Ответ 1
Вы можете настроить сортировку. Попробуйте найти исходный код, чтобы узнать, как создается Collator для немецкого языка, как описано в этом ответе.
Затем адаптируйте его к вашим потребностям. tutorial дает начальную точку. Но не нужно делать всю работу, кто-то еще это сделал: см. Это сообщение в блоге, посвященное той же проблеме для чешского языка.
Суть решения, связанного выше:
String rules = ((RuleBasedCollator) Collator.getInstance(Locale.GERMANY)).getRules();
RuleBasedCollator correctedCollator
= new RuleBasedCollator(rules.replaceAll("<'\u005f'", "<' '<'\u005f'"));
Это добавляет правило для символа пробела перед правилом для подчеркивания.
Я признаюсь, что не проверял это лично.
Ответ 2
Если вы не можете изменить локаль по некоторым причинам, я бы предложил вам написать все самостоятельно. Вот некоторые идеи, хотя этот код не является полным и не работает:
-
Вместо того, чтобы иметь список строк, создайте свои собственные объекты, выполнив сопоставимые значения:
public class myString implements Comparable<myString> {
private String name;
public myString(String name) {
this.name = name;
}
}
-
Затем вам нужно будет реализовать (см. пример здесь)
public int compareTo(myString compareMyString) {
...
}
-
Теперь идет сложная часть:
-
Чтобы сравнить ваши строки, вам нужно разбить их (это приведет к массиву строк). Например:
// Original String
"Barr Burt"
// Splitted String
[0]: "Barr"
[1]: "Burt"
-
Вам нужно будет сравнивать слова один за другим. Создайте функцию, выполняющую что-то вроде этого (это псевдокод: "this.words [i]" вызывает i-е слово "this.name" )
public int compareWords(myString compareMyString, int i)
{
if (this.words[i] < compareMyString.words[i])
return -1; // "this" should come before "compareMyString"
if (this.words[i] > compareMyString.words[i])
return 1; // "this" should come after "compareMyString"
if (this.words[i] == compareMyString.words[i])
return compareWords(i+1);
}
-
И затем compareTo
:
public int compareTo(myString compareMyString) {
return compareWords(compareMyString, 0);
}