W3docs

Come invertire una stringa in Java

Inverti una stringa Java con StringBuilder.reverse, array di caratteri, ricorsione o stream.

Invertire una stringa significa produrre una nuova stringa i cui caratteri appaiono nell'ordine opposto — "Hello" diventa "olleH". Poiché le stringhe Java sono immutabili, non si può mai invertire una stringa in place; bisogna sempre costruirne una nuova. Esistono diversi modi idiomatici per farlo, e la scelta giusta dipende dal fatto che si voglia il codice più breve, il minor numero di dipendenze o la gestione corretta dei caratteri al di fuori del piano multilingue di base (come le emoji).

Questa pagina illustra quattro approcci — il metodo integrato StringBuilder.reverse, un ciclo manuale su un array di caratteri, la ricorsione e una pipeline di stream — li confronta in una tabella, poi esegue tutti e quattro sullo stesso input più due casi limite, così puoi vedere esattamente come si comportano.

Il modo idiomatico: StringBuilder.reverse

La libreria standard dispone già di un metodo reverse su StringBuilder (e StringBuffer). È la risposta in quasi ogni situazione:

String reversed = new StringBuilder("Hello").reverse().toString();
// reversed = "olleH"

Racchiudi la stringa originale in un StringBuilder, chiama reverse() e poi toString() per ottenere una String normale. È veloce (un singolo passaggio, senza boxing) e si legge chiaramente. Un ulteriore vantaggio: StringBuilder.reverse() è surrogate-aware — mantiene insieme i due char di un code point supplementare (come un'emoji) invece di invertirli e produrre caratteri corrotti.

Ciclo manuale su un array di char

Quando si vogliono vedere i meccanismi interni — o ci si trova in un ambiente in cui non è possibile usare StringBuilder — si scorre un char[] dall'ultimo indice fino al primo:

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();

Questo è esattamente ciò che fa internamente StringBuilder.reverse, senza la gestione dei surrogati. Evita di costruire il risultato con reversed += chars[i] su una String semplice: la concatenazione di stringhe in un ciclo crea un nuovo oggetto a ogni iterazione e trasforma un'operazione O(n) in O(n²).

Ricorsione e stream

Una soluzione ricorsiva si legge come la sua definizione — l'inverso di una stringa è l'inverso della sua coda seguito dal suo primo carattere:

static String reverse(String s) {
  if (s.isEmpty()) return s;
  return reverse(s.substring(1)) + s.charAt(0);
}

È elegante, ma alloca una sottostringa per ogni chiamata e può causare un overflow dello stack su input molto lunghi, quindi trattala come uno strumento didattico piuttosto che codice di produzione. Una soluzione in una riga basata su stream evita la ricorsione ma è la meno leggibile di tutte:

String reversed = "Hello".chars()
    .mapToObj(c -> String.valueOf((char) c))
    .reduce("", (a, b) -> b + a);
ApproccioRigheVelocitàSicuro per i surrogati
StringBuilder.reverse1Veloce
Ciclo manuale su char array~5VeloceNo
Ricorsione~4Lento, limitato dallo stackNo
Stream + reduce~3Lento (ricostruisce la stringa)No

Un esempio pratico

Questo programma inverte "Hello" in quattro modi diversi, conferma che tutti concordano, poi verifica due casi limite: una stringa vuota e una stringa contenente un'emoji (una coppia di surrogati).

java— editable, runs on the server

Cosa osservare dall'esecuzione:

  • Tutti e quattro gli approcci stampano olleH, quindi sono intercambiabili per testo ASCII semplice — la scelta tra loro riguarda la leggibilità e le prestazioni, non la correttezza.
  • StringBuilder.reverse ha prodotto il risultato in un'unica espressione, ed è per questo che è la raccomandazione predefinita rispetto al ciclo, alla ricorsione e alle varianti con stream.
  • Invertire la stringa vuota restituisce la stringa vuota (''), confermando che i metodi sono sicuri da chiamare senza un controllo della lunghezza — nessun caso speciale necessario.
  • Il reverse ricorsivo si è concluso perché il suo caso base (s.isEmpty()) interrompe la catena di chiamate a substring(1); senza quel controllo non avrebbe mai restituito un risultato.
  • naive emoji ok: true mostra che StringBuilder.reverse ha mantenuto intatta l'emoji con la faccina sorridente — ha spostato la coppia di surrogati come un'unità. Un ciclo char-per-char scritto a mano avrebbe separato quella coppia e corrotto l'emoji.

Pratica

Pratica
Quale metodo integrato inverte una stringa in un'unica espressione e mantiene intatte anche le coppie di surrogati (come le emoji)?
Quale metodo integrato inverte una stringa in un'unica espressione e mantiene intatte anche le coppie di surrogati (come le emoji)?

Argomenti correlati

Was this page helpful?