W3docs

Как перевернуть строку в Java

Переворот строки в Java с помощью StringBuilder.reverse, массивов символов, рекурсии или потоков.

Переворот строки означает создание новой строки, символы которой расположены в обратном порядке — "Hello" превращается в "olleH". Поскольку строки в Java неизменяемы, перевернуть строку на месте невозможно — всегда создаётся новая строка. Существует несколько идиоматических способов сделать это, и правильный выбор зависит от того, нужен ли вам наиболее короткий код, минимум зависимостей или корректная обработка символов вне базовой многоязычной плоскости (например, эмодзи).

На этой странице рассматриваются четыре подхода — встроенный StringBuilder.reverse, ручной цикл по массиву символов, рекурсия и потоковый конвейер — сравниваются в таблице, а затем все четыре применяются к одному входному значению и двум граничным случаям, чтобы вы могли видеть их поведение в точности.

Идиоматический способ: StringBuilder.reverse

Стандартная библиотека уже имеет метод обращения строки в StringBuilderStringBuffer). Это ответ почти в каждой ситуации:

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.reverse1БыстроДа
Ручной цикл по char-массиву~5БыстроНет
Рекурсия~4Медленно, ограничено стекомНет
Stream + reduce~3Медленно (пересборка строки)Нет

Пример с разбором

Эта программа переворачивает "Hello" четырьмя разными способами, убеждается, что все они дают одинаковый результат, затем проверяет два граничных случая: пустую строку и строку, содержащую эмодзи (суррогатную пару).

java— editable, runs on the server

Что следует вынести из запуска:

  • Все четыре подхода выводят olleH, то есть они взаимозаменяемы для обычного ASCII-текста — выбор между ними касается читаемости и производительности, но не корректности.
  • StringBuilder.reverse дал результат в одном выражении, поэтому он является рекомендацией по умолчанию по сравнению с вариантами на основе цикла, рекурсии и потока.
  • Переворот пустой строки возвращает пустую строку (''), подтверждая, что методы безопасно вызывать без проверки длины — никаких специальных случаев не требуется.
  • Рекурсивный reverse завершился, потому что его базовый случай (s.isEmpty()) останавливает цепочку вызовов substring(1); без этого ограничителя он никогда бы не вернул результат.
  • naive emoji ok: true показывает, что StringBuilder.reverse сохранил эмодзи с улыбающимся лицом нетронутым — суррогатная пара перемещается как единица. Самописный цикл по char разбил бы эту пару и испортил эмодзи.

Практика

Практика
Какой встроенный метод переворачивает строку в одном выражении и при этом сохраняет суррогатные пары (например, эмодзи) нетронутыми?
Какой встроенный метод переворачивает строку в одном выражении и при этом сохраняет суррогатные пары (например, эмодзи) нетронутыми?

Связанные темы

Was this page helpful?