Comment inverser une chaîne en Java
Inversez une chaîne Java avec StringBuilder.reverse, les tableaux de caractères, la récursion ou les streams.
Inverser une chaîne consiste à produire une nouvelle chaîne dont les caractères apparaissent dans l'ordre inverse — "Hello" devient "olleH". Comme les chaînes Java sont immuables, vous ne pouvez jamais inverser une chaîne sur place ; vous devez toujours en construire une nouvelle. Il existe plusieurs façons idiomatiques de le faire, et le bon choix dépend de si vous souhaitez le code le plus court, le moins de dépendances, ou une gestion correcte des caractères hors du plan multilingue de base (comme les emoji).
Cette page couvre quatre approches — le StringBuilder.reverse intégré, une boucle manuelle sur un tableau de caractères, la récursion et un pipeline de stream — les compare dans un tableau, puis exécute les quatre sur la même entrée plus deux cas limites pour vous montrer exactement leur comportement.
La méthode idiomatique : StringBuilder.reverse
La bibliothèque standard dispose déjà d'une méthode reverse sur StringBuilder (et StringBuffer). C'est la réponse dans presque toutes les situations :
String reversed = new StringBuilder("Hello").reverse().toString();
// reversed = "olleH"Encapsulez la chaîne d'origine dans un StringBuilder, appelez reverse(), et appelez toString() pour obtenir un String ordinaire en retour. C'est rapide (un seul passage, sans boxing) et se lit clairement. Un avantage supplémentaire : StringBuilder.reverse() est conscient des surrogates — il maintient les deux chars d'un point de code supplémentaire (comme un emoji) ensemble au lieu de les inverser et de produire des caractères corrompus.
Boucle manuelle sur un tableau de caractères
Lorsque vous souhaitez voir les mécanismes — ou que vous êtes dans un environnement où vous ne pouvez pas utiliser StringBuilder — parcourez un char[] depuis le dernier index jusqu'au premier :
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();C'est exactement ce que fait StringBuilder.reverse en interne, sans la gestion des surrogates. Évitez de construire le résultat avec reversed += chars[i] sur un String brut : la concaténation de chaînes dans une boucle crée un nouvel objet à chaque itération et transforme un travail O(n) en O(n²).
Récursion et streams
Une solution récursive se lit comme sa définition — l'inverse d'une chaîne est l'inverse de sa queue suivi de son premier caractère :
static String reverse(String s) {
if (s.isEmpty()) return s;
return reverse(s.substring(1)) + s.charAt(0);
}C'est élégant mais alloue une sous-chaîne par appel et peut provoquer un débordement de pile sur des entrées très longues, donc traitez-la comme un outil pédagogique plutôt que du code de production. Une solution en une ligne basée sur les streams évite la récursion mais est la moins lisible du groupe :
String reversed = "Hello".chars()
.mapToObj(c -> String.valueOf((char) c))
.reduce("", (a, b) -> b + a);| Approche | Lignes | Vitesse | Sûr pour les surrogates |
|---|---|---|---|
StringBuilder.reverse | 1 | Rapide | Oui |
| Boucle manuelle sur char-array | ~5 | Rapide | Non |
| Récursion | ~4 | Lente, limitée par la pile | Non |
| Stream + reduce | ~3 | Lente (reconstruit la chaîne) | Non |
Un exemple concret
Ce programme inverse "Hello" de quatre façons différentes, confirme qu'elles sont toutes d'accord, puis vérifie deux cas limites : une chaîne vide et une chaîne contenant un emoji (une paire de surrogates).
Ce que l'on retient de l'exécution :
- Les quatre approches affichent
olleH, donc elles sont interchangeables pour du texte ASCII ordinaire — le choix entre elles concerne la lisibilité et les performances, pas l'exactitude. StringBuilder.reversea produit le résultat en une seule expression, c'est pourquoi c'est la recommandation par défaut par rapport aux variantes avec boucle, récursion et stream.- Inverser la chaîne vide renvoie la chaîne vide (
''), confirmant que les méthodes sont sûres à appeler sans vérification de longueur — aucun cas particulier n'est nécessaire. - Le
reverserécursif s'est terminé car son cas de base (s.isEmpty()) interrompt la chaîne d'appelssubstring(1); sans cette garde, il ne retournerait jamais. naive emoji ok: truemontre queStringBuilder.reversea maintenu l'emoji de visage souriant intact — il a déplacé la paire de surrogates comme une unité. Une bouclechar-par-charécrite manuellement séparerait cette paire et corromprait l'emoji.
Pratique
Sujets connexes
- Méthodes Java String — la boîte à outils complète pour découper, rechercher et transformer des chaînes.
- Java StringBuilder — le tampon mutable derrière
reverse()et la construction efficace de chaînes. - Immuabilité des chaînes — pourquoi un
Stringne peut jamais être modifié sur place.