Как отсортировать список(List) по частоте повторения элемента
В общем, я новичок в программировании и буду рад если кто-нибудь поможет мне с моей задачей. Задача заключается в том чтоб принять текстовый файл(на английском), например какую-нибудь книгу и разбить текст на слова. Затем программа должна подсчитать каждое вхождение слова и распечатать в System.out все идентифицированные слова и количество их вхождений в определенном порядке: более популярные слова идут первыми. Решение не должно использовать потоки JAVA.
На данный момент я дошёл до этого момента, но дальше не могу понять, как выполнить подсчёт и сортировку.
public static List<String> splitText(String text){
List<String> words = new ArrayList<String>();
BreakIterator breakIterator = BreakIterator.getWordInstance();
breakIterator.setText(text);
int lastIndex = breakIterator.first();
while (BreakIterator.DONE != lastIndex) {
int firstIndex = lastIndex;
lastIndex = breakIterator.next();
if (lastIndex != BreakIterator.DONE && Character.isLetterOrDigit(text.charAt(firstIndex))) {
words.add(text.substring(firstIndex, lastIndex));
}
}
System.out.println(words);
return words;
}
public static void main(String[] args) throws IOException {
String fileName = "AG.txt";
FileReader fileReader = new FileReader(fileName);
try (BufferedReader bufferedReader = new BufferedReader(fileReader)) {
String line;
while((line = bufferedReader.readLine()) != null) {
splitText(line);
}
} catch (IOException e) {
System.out.println("Error" + e);
}
}
Ответы (1 шт):
Если считаются слова и количество их вхождений в текст, то строится карта частот слов Map<String, Integer>, а не просто список. Содержимое карты можно отсортировать при помощи SortedSet/TreeSet с кастомизированным компаратором, и затем уже можно проитерировать упорядоченный набор пар "слово-частота" и добавить слова в результирующий список в нужном порядке.
Для вычисления частоты слова стоит использовать метод Map::merge.
Использование Stream API не обязательно.
public static List<String> splitText(String text) {
//
Map<String, Integer> words = new HashMap<>();
BreakIterator breakIterator = BreakIterator.getWordInstance();
breakIterator.setText(text);
int lastIndex = breakIterator.first();
while (BreakIterator.DONE != lastIndex) {
int firstIndex = lastIndex;
lastIndex = breakIterator.next();
if (lastIndex != BreakIterator.DONE && Character.isLetterOrDigit(text.charAt(firstIndex))) {
String word = text.substring(firstIndex, lastIndex);
words.merge(word, 1, Integer::sum);
}
}
// отсортировать по убыванию частоты а затем в алфавитном порядке
SortedSet<Map.Entry<String, Integer>> sorted = new TreeSet<>(
Map.Entry.<String, Integer>comparingByValue().reversed()
.thenComparing(Map.Entry.comparingByKey())
);
sorted.addAll(words.entrySet());
System.out.println(sorted);
List<String> result = new ArrayList<>();
for (Map.Entry<String, Integer> e : sorted) {
result.add(e.getKey());
}
return result;
}