Я хотел бы отсортировать список своих объектов по полю их строкового имени. Но в этих именах есть некоторые полированные символы, и из-за этого сортировка некорректна. Я провел небольшое исследование проблемы и выяснил, что мне следует использовать что-то вроде:
Collections.sort(myList, Collator.getInstance());
Но проблема в том, что это работает только тогда, когда я пытаюсь отсортировать список строк. Когда я пытаюсь отсортировать список своих объектов, я получаю java.lang.ClassCastException.
Как я могу отсортировать список моих объектов в алфавитном порядке на польском языке?
Мой объект выглядит примерно так:
public class MyObject implements Comparable<MyObject>{
private String name;
...
@Override
public int compareTo(@NonNull MyObject object) {
return name.compareTo(object.getName());
}
А сейчас пытаюсь отсортировать вот так:
List<MyObject> myList = DataProvider.getInstance().getListOfObjects();
Collections.sort(myList, Collator.getInstance());




Я считаю, что в Collatorдокументация есть некоторая двусмысленность.
Collator - это Comparator<Object>, но он действительно нацелен на выполнение
locale-sensitive String comparison (emphasis mine).
Вы можете лучше увидеть это в документация конкретной реализации Collator#compare:
This implementation merely returns compare
((String)o1, (String)o2).
ClassCastException, который вы получаете, вероятно, связан с тем, что очевидно, что MyObject не является String.
Я бы попытался перенести использование Collator в вашу фактическую реализацию compareTo:
Collections.sort(myList);
... и в вашей реализации compareTo:
Collator.getInstance().compare(name, object.getName());
Обратите внимание, что идиома Collator.getInstance() использует Locale по умолчанию.
Следовательно, если вы планируете использовать несколько Locale для сравнения ваших объектов в зависимости от контекста, вам может быть лучше выполнить сортировку с помощью специального Comparator, который позволяет вводить Locale и использовать Collator под капотом.
Я реализовал сортировку так, как вы предложили, используя коллатор внутри реализации compareTo. И теперь я получаю ошибку: java.lang.IllegalArgumentException: Comparison method violates its general contract!
@matip не произошел в моей репликации (с вашими открытыми условиями), однако я не аннотировал параметр как @NonNull. Если вы не добавили дополнительный код по сравнению с вашим вопросом, попробуйте избавиться от него, так как это может нарушить подпись переопределения, насколько мне известно. Фактически, вы должны обрабатывать случаи null в теле compareTo.
Хорошо, что я обрабатываю нулевые случаи внутри тела compareTo. Только когда имена не равны нулю, я использую Collator.getInstance().compare
@matip, вероятно, что-то не так с вашей реализацией, но об этом трудно догадаться без реального кода.
Мне удалось заставить это работать. Когда я обрабатывал нулевой регистр в методе compareTo, я возвращал 0. Теперь я возвращаю 1 в таких случаях, и все работает.
@matip, который это объясняет, да. 0 будет означать, что объекты должны считаться равными, что не имело бы смысла, если бы один из них был null, а тот, который выполнял compareTo, явно не был :)
Collator используется для сравнения строк, вы можете извлечь имя и передать их в Collator:
myList.sort((o1, o2) -> Collator.getInstance().compare(o1.getName(), o2.getName()));
Может ли
nameсодержать также непольские символы, такие как немецкий, французский? Если да, то как бы вы их заказать?