При подсчете слов в строке появляется {}
Делаю программу для подсчёта повторения каждого слово из файла что приходит в метод.
Я хочу чтоб на выходе возвращался String вот в таком виде пушкин - 20, для каждого слово. А мне
возвращается пустые скобки {}. Как решить проблему?
public String countWords(List<String> lines) {
Map<String, Integer> wordCount = new HashMap<String, Integer>();
String learn = lines.toString().toLowerCase().replaceAll("[^a-zA-Z0-9]", " ");
String[] words = learn.split(" ");
for(String word: words) {
Integer count = wordCount.get(word);
wordCount.put(word, (count==null) ? 1 : count+1);
}
return wordCount.toString();
}
}
Ответы (1 шт):
Проблема в том, что .replaceAll("[^a-zA-Z0-9]", " ") заменяет все символы кроме цифр и английских/латинских букв на пробелы. Следовательно, все слова на русском удаляются, а результирующая мапа получается пустой, о чём и говорит результат в виде пары фигурных скобок {}.
Для фильтрации букв можно использовать POSIX-классы \p{L} для букв и \p{N} для цифр: replaceAll("(?u)[^\\p{L}\\p{N}]", " ").
Также стоит отфильтровать пустые строки - либо уже в цикле, либо используя разбиение по группам пробельных символов \s+:
String[] words = learn.trim().split("\\s+");
Также, для подсчёта частоты можно использовать более лаконичный метод Map::merge:
public static String countWords(List<String> lines) {
Map<String, Integer> wordCount = new HashMap<String, Integer>();
for (String word : lines.toString().toLowerCase()
.replaceAll("(?u)[^\\p{L}\\p{N}]", " ")
.trim().split("\\s+")
) {
wordCount.merge(word, 1, Integer::sum);
}
return wordCount.toString();
}
Тест:
System.out.println(countWords(Arrays.asList("Пушкин пушкин -- ПУШКИН", "test test2 test")));
// -> {test2=1, test=2, пушкин=3}
Следует отметить, что эта задачу удобно решить, используя Stream API, в частности, Collectors.groupingBy и Collectors.counting для подсчета частоты слов, а затем Collectors.joining для преобразования в строку:
public static String countWords(List<String> lines) {
return lines
.stream() // поток строк
.map(line -> line.toLowerCase()
.replaceAll("(?u)[^\\p{L}\\p{N}]", " ")
) // поток строк в нижнем регистре без ненужных символов
.flatMap(line -> Arrays.stream(line.split("\\s+"))) // поток слов
.collect(Collectors.groupingBy(
word -> word,
TreeMap::new, // сортировка по ключу по умолчанию
Collectors.counting()
)) // HashMap<String, Long> - словарь со значениями частот
.entrySet()
.stream()
.sorted(Map.Entry.<String, Long>comparingByValue().reversed())
.map(e -> e.getKey() + " - " + e.getValue())
.collect(Collectors.joining("\n")); // результат
}
Тест:
System.out.println(countWords(Arrays.asList("Пушкин пушкин -- ПУШКИН наше", "тигруля красив котенок игрив", "красив манул игрив")));
Результат:
пушкин - 3
игрив - 2
красив - 2
котенок - 1
манул - 1
наше - 1
тигруля - 1