Как правильно разбивать текст на слова с учетом разных разделителей
Что проверяют
Понимаете ли вы, что «разбить на слова» это прежде всего вопрос требований, и знаете ли подводные камни String.split. Следом обычно спрашивают про дефисы, апострофы, кириллицу и производительность на больших текстах.
Как отвечать
Начните с уточнений: что считается словом («что-то», «don’t», «C++», числа), нужны ли пустые токены, какого размера вход. Потом варианты:
String.split(regex): аргумент это регулярное выражение, а не строка. Для набора разделителей подходитtext.split("[\\s,.;:!?]+"). Хвостовые пустые строки отбрасываются, а ведущая остаётся:" hello".split("\\s+")даст["", "hello"], поэтому сначалаstrip()или фильтр пустых;- поиск слов вместо разделителей: надёжнее описать само слово, а не всё, что между словами.
Pattern.compile("[\\p{L}\\p{N}]+(?:['-][\\p{L}\\p{N}]+)*")иmatcher.results().map(MatchResult::group)(Java 9+). Новый знак препинания в тексте такую логику не сломает; BreakIterator.getWordInstance(locale): границы слов по правилам языка, полезен для многоязычного текста;StringTokenizer: только одиночные символы-разделители, без регулярок, считается устаревшим. Упомянуть можно, выбирать не стоит.
Про производительность: String.split с одним символом, который не является метасимволом regex, идёт по быстрому пути без компиляции шаблона, а сложное выражение компилируется при каждом вызове. Поэтому в горячем коде шаблон держат в private static final Pattern, а для больших входов используют Pattern.splitAsStream() или Scanner с useDelimiter(), чтобы не держать все токены в массиве.
Где спотыкаются
Пишут split(".") или split("|"). Точка совпадает с любым символом, и результат пустой, а | режет строку на отдельные символы. Нужно экранировать или обернуть в Pattern.quote().
Используют \\W как разделитель и ломают русский текст. В Java \w по умолчанию только ASCII, кириллица попадает в разделители. Нужен флаг Pattern.UNICODE_CHARACTER_CLASS или классы \p{L}.
Не проверяют крайние случаи: пустую строку, строку из одних разделителей, ведущий пробел. "".split(",") возвращает массив из одной пустой строки, а не пустой массив.