Как отсортировать слова по количеству вхождений и по алфавиту
Что проверяют
Базовое владение коллекциями и Comparator: подсчёт через Map, составная сортировка, аккуратный разбор строки. Следом обычно просят переписать на Stream API, оценить сложность или вернуть только топ K слов.
Как отвечать
Решение в три шага, и на каждом есть что сказать:
- разбиение:
split(" ")ломается на двойных пробелах и знаках препинания. Лучшеtext.toLowerCase(Locale.ROOT).split("[^\\p{L}\\p{N}]+")и отбросить пустые строки: если текст начинается с разделителя, первый элемент массива будет пустым. Обычный\\Wв Java без флагаUNICODE_CHARACTER_CLASSне считает кириллицу буквами; - подсчёт:
counts.merge(word, 1, Integer::sum)вHashMap. Или сразу потоком:Collectors.groupingBy(Function.identity(), Collectors.counting()), значения тогдаLong; - сортировка: список записей и компаратор
Map.Entry.<String, Long>comparingByValue().reversed().thenComparing(Map.Entry.comparingByKey()). Явный тип в угловых скобках нужен: без него послеreversed()компилятор не выводит типы и код не собирается.
Сложность: при n словах и m уникальных подсчёт стоит O(n), сортировка O(m log m). Если нужен только топ K, держите PriorityQueue размера K и получите O(m log K), на больших текстах это заметно дешевле.
Про «алфавит» стоит уточнить у интервьюера. String.compareTo сравнивает коды символов UTF-16, поэтому заглавные идут раньше строчных, а «ё» уезжает в конец, после «я». Для правильного русского порядка нужен Collator.getInstance(Locale.forLanguageTag("ru")) вторым ключом сравнения.
Где спотыкаются
Пытаются отсортировать саму HashMap, у которой нет порядка. Сортировать нужно список записей, а для результата с сохранённым порядком есть LinkedHashMap.
Пишут компаратор через вычитание b.getValue() - a.getValue(). На целых это работает до первого переполнения, надёжнее Integer.compare или готовые компараторы.
Забывают второй ключ сортировки, и слова с одинаковой частотой выходят в непредсказуемом порядке.