Сортировка объектов по полю с дополнительной логикой
Есть класс Word, у него есть поле String word. Создаем список из объектов List<Word> words.
Нужно отсортировать объекты по количеству вхождений определенной буквы в поле String Word word.
Подскажите, как лучше отсортировать такой список? Comparable и Comparator здесь не подходят (ну или я не понял как), т.к. буква, по которой нужно сортировать заранее не известна, и нам еще нужно подсчитать ее количество в каждом слове.
public class Word {
private final String word;
public Word(String word) {
this.word = word;
}
public String getWord() {
return word;
}
}
Ответы (2 шт):
Для начала можно написать метод, который считает количество вхождений буквы в Word:
/**
* Подсчет количества вхождений буквы в слово
*/
static int countLetter(Word word, char letter) {
String w = word.word;
return w.length() - w.replace(letter + "", "").length();
}
Затем его можно использовать и в компараторе с методом sort:
words.sort((Word o1, Word o2) -> {
int c1 = countLetter(o1, 'a');
int c2 = countLetter(o2, 'a');
return Integer.compare(c1, c2);
});
И со стримами, если нужно:
List<Word> sortedWords = words.stream()
.sorted(Comparator.comparing(w -> countLetter(w, 'a')))
.collect(Collectors.toList());
Оба метода могут рассчитывать количество более одного раза для одного слова. Если количество слов будет огромным и возникнут проблемы с производительностью, то может потребоваться предварительно рассчитать количество вхождений для каждого слова (создать для этого отдельный массив/класс/пару значений).
Если для производительности некритично вычисление числа вхождений буквы при каждом сравнении, то нужно просто сделать букву полем компаратора и внутри метода сравнения выполнять подсчёт.
Если нужно сделать более оптимально, то создаём массив пар ссылка, количество. Компаратор по-прежнему получает букву в конструкторе, но обращается к уже посчитанному количеству вхождений. А после сортировки проходим по новому массиву и из него присваиваем элементы в оригинальный.
При желании вместо передачи в конструктор можно использовать замыкание.