Как перевернуть строку в Java
Переворот строки в Java с помощью StringBuilder.reverse, массивов символов, рекурсии или потоков.
Переворот строки означает создание новой строки, символы которой расположены в обратном порядке — "Hello" превращается в "olleH". Поскольку строки в Java неизменяемы, перевернуть строку на месте невозможно — всегда создаётся новая строка. Существует несколько идиоматических способов сделать это, и правильный выбор зависит от того, нужен ли вам наиболее короткий код, минимум зависимостей или корректная обработка символов вне базовой многоязычной плоскости (например, эмодзи).
На этой странице рассматриваются четыре подхода — встроенный StringBuilder.reverse, ручной цикл по массиву символов, рекурсия и потоковый конвейер — сравниваются в таблице, а затем все четыре применяются к одному входному значению и двум граничным случаям, чтобы вы могли видеть их поведение в точности.
Идиоматический способ: StringBuilder.reverse
Стандартная библиотека уже имеет метод обращения строки в StringBuilder (и StringBuffer). Это ответ почти в каждой ситуации:
String reversed = new StringBuilder("Hello").reverse().toString();
// reversed = "olleH"Оберните исходную строку в StringBuilder, вызовите reverse(), а затем toString(), чтобы получить обычный String. Это быстро (один проход, без упаковки) и читается понятно. Приятный бонус: StringBuilder.reverse() учитывает суррогатные пары — он сохраняет два charа дополнительной кодовой точки (например, эмодзи) вместе, не переворачивая их и не порождая мусор.
Ручной цикл по массиву символов
Когда вы хотите увидеть механику — или находитесь в среде, где нельзя использовать StringBuilder — пройдитесь по char[] от последнего индекса до первого:
char[] chars = "Hello".toCharArray();
StringBuilder out = new StringBuilder();
for (int i = chars.length - 1; i >= 0; i--) {
out.append(chars[i]);
}
String reversed = out.toString();Это именно то, что StringBuilder.reverse делает внутри, за исключением обработки суррогатных пар. Избегайте построения результата через reversed += chars[i] на обычном String: конкатенация строк в цикле создаёт новый объект на каждой итерации и превращает задачу O(n) в O(n²).
Рекурсия и потоки
Рекурсивное решение читается как определение — переворот строки есть переворот её хвоста, за которым следует первый символ:
static String reverse(String s) {
if (s.isEmpty()) return s;
return reverse(s.substring(1)) + s.charAt(0);
}Оно элегантно, но выделяет подстроку на каждом вызове и может вызвать переполнение стека на очень длинных входных данных, поэтому воспринимайте его как учебный инструмент, а не код для продакшена. Однострочник на основе потоков избегает рекурсии, но является наименее читаемым из всех:
String reversed = "Hello".chars()
.mapToObj(c -> String.valueOf((char) c))
.reduce("", (a, b) -> b + a);| Подход | Строк | Скорость | Сохраняет суррогаты |
|---|---|---|---|
StringBuilder.reverse | 1 | Быстро | Да |
| Ручной цикл по char-массиву | ~5 | Быстро | Нет |
| Рекурсия | ~4 | Медленно, ограничено стеком | Нет |
| Stream + reduce | ~3 | Медленно (пересборка строки) | Нет |
Пример с разбором
Эта программа переворачивает "Hello" четырьмя разными способами, убеждается, что все они дают одинаковый результат, затем проверяет два граничных случая: пустую строку и строку, содержащую эмодзи (суррогатную пару).
Что следует вынести из запуска:
- Все четыре подхода выводят
olleH, то есть они взаимозаменяемы для обычного ASCII-текста — выбор между ними касается читаемости и производительности, но не корректности. StringBuilder.reverseдал результат в одном выражении, поэтому он является рекомендацией по умолчанию по сравнению с вариантами на основе цикла, рекурсии и потока.- Переворот пустой строки возвращает пустую строку (
''), подтверждая, что методы безопасно вызывать без проверки длины — никаких специальных случаев не требуется. - Рекурсивный
reverseзавершился, потому что его базовый случай (s.isEmpty()) останавливает цепочку вызововsubstring(1); без этого ограничителя он никогда бы не вернул результат. naive emoji ok: trueпоказывает, чтоStringBuilder.reverseсохранил эмодзи с улыбающимся лицом нетронутым — суррогатная пара перемещается как единица. Самописный цикл поcharразбил бы эту пару и испортил эмодзи.
Практика
Связанные темы
- Методы строк Java — полный набор инструментов для нарезки, поиска и преобразования строк.
- Java StringBuilder — изменяемый буфер за
reverse()и эффективным построением строк. - Неизменяемость строк — почему
Stringне может быть изменён на месте.