La Classe StringBuffer in Java

Concetti Chiave
  • La classe StringBuffer in Java consente di gestire stringhe modificabili, a differenza della classe String che rappresenta stringhe immutabili.
  • StringBuffer fornisce metodi per aggiungere, inserire, eliminare e sostituire caratteri e sotto-stringhe, rendendo la manipolazione delle stringhe più efficiente.
  • I metodi come append(), insert(), delete(), replace() e reverse() offrono funzionalità avanzate per lavorare con le stringhe in modo dinamico.
  • La capacità di StringBuffer può essere gestita tramite metodi come ensureCapacity() e trimToSize(), permettendo di ottimizzare l'uso della memoria.

La Classe StringBuffer

La libreria standard di Java mette a disposizione la classe StringBuffer che supporta una stringa modificabile.

Come sappiamo, un oggetto di tipo String rappresenta sequenze di caratteri immutabili a lunghezza fissa. Al contrario, StringBuffer rappresenta sequenze di caratteri espandibili e modificabili. StringBuffer può avere caratteri e sotto-stringhe inseriti nel mezzo o aggiunti alla fine. StringBuffer crescerà automaticamente per fare spazio a tali aggiunte e spesso ha più caratteri pre-allocati di quanti ne siano effettivamente necessari, per consentire spazio per la crescita.

Vediamo nel dettaglio come funziona StringBuffer.

Costruttori di StringBuffer

StringBuffer definisce questi quattro costruttori:

StringBuffer()
StringBuffer(int dimensione)
StringBuffer(String str)
StringBuffer(CharSequence caratteri)
  • Il costruttore predefinito (quello senza parametri) riserva spazio per 16 caratteri senza riallocazione.
  • La seconda versione accetta un argomento intero, dimensione, che imposta esplicitamente la dimensione del buffer.
  • La terza versione accetta un argomento String che imposta il contenuto iniziale dell'oggetto StringBuffer e riserva spazio per altri 16 caratteri senza riallocazione.
  • Il quarto costruttore crea un oggetto che contiene la sequenza di caratteri contenuta in caratteri e riserva spazio per altri 16 caratteri.

StringBuffer alloca spazio per 16 caratteri aggiuntivi quando non viene richiesta una lunghezza specifica del buffer, perché la riallocazione è un processo costoso in termini di tempo. Inoltre, le riallocazioni frequenti possono frammentare la memoria. Allocando spazio per alcuni caratteri extra, StringBuffer riduce il numero di riallocazioni che hanno luogo.

i metodi length e capacity

La lunghezza corrente di un StringBuffer può essere trovata tramite il metodo length(), mentre la capacità totale allocata può essere trovata attraverso il metodo capacity(). Hanno le seguenti forme generali:

int length()
int capacity()

Ecco un esempio:

// Lunghezza di StringBuffer vs. capacità.
class DemoStringBuffer {

    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Ciao");
        System.out.println("buffer = " + sb);
        System.out.println("lunghezza = " + sb.length());
        System.out.println("capacità = " + sb.capacity());
    }

}

Ecco l'output di questo programma, che mostra come StringBuffer riserva spazio extra per manipolazioni aggiuntive:

buffer = Ciao
lunghezza = 4
capacità = 20

Poiché sb è inizializzato con la stringa "Ciao" quando viene creato, la sua lunghezza è 4. La sua capacità è 20 perché viene automaticamente aggiunto spazio per 16 caratteri aggiuntivi.

Il metodo ensureCapacity

Se vogliamo preallocare spazio per un certo numero di caratteri dopo che un StringBuffer è stato costruito, possiamo usare ensureCapacity() per impostare la dimensione del buffer.

Questo è utile se sappiamo in anticipo che aggiungeremo un gran numero di piccole stringhe a un StringBuffer. ensureCapacity() ha questa forma generale:

void ensureCapacity(int capacitaMinima)

Qui, capacitaMinima specifica la dimensione minima del buffer. In ogni caso, il parametro capacitaMinima è un suggerimento. Per motivi di efficienza, StringBuffer potrebbe allocare più spazio di quanto richiesto.

Il metodo setLength

Per impostare la lunghezza della stringa all'interno di un oggetto StringBuffer, si può usare setLength(). La sua forma generale è mostrata qui:

void setLength(int lunghezza)

Qui, lunghezza specifica la lunghezza della stringa. Questo valore deve essere non negativo.

Quando si aumenta la dimensione della stringa, caratteri nulli, ossia \0, vengono aggiunti alla fine. Se si chiama setLength() con un valore inferiore al valore corrente restituito da length(), allora i caratteri memorizzati oltre la nuova lunghezza andranno persi. Il programma di esempio demoSetCharAt nella sezione seguente utilizza setLength() per accorciare un StringBuffer.

I metodi charAt e setCharAt

Il valore di un singolo carattere può essere ottenuto da un StringBuffer tramite il metodo charAt(). È possibile impostare il valore di un carattere all'interno di un StringBuffer utilizzando setCharAt(). Le loro forme generali sono mostrate qui:

char charAt(int dove)
void setCharAt(int dove, char ch)

Per charAt(), dove specifica l'indice del carattere che viene ottenuto. Per setCharAt(), dove specifica l'indice del carattere che viene impostato, e ch specifica il nuovo valore di quel carattere. Per entrambi i metodi, dove deve essere non negativo e non deve specificare una posizione oltre la fine della stringa.

L'esempio seguente dimostra charAt() e setCharAt():

// Dimostra charAt() e setCharAt().
class DemoSetCharAt {

    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Ciao");

        System.out.println("buffer prima = " + sb);
        System.out.println("charAt(1) prima = " + sb.charAt(1));

        sb.setCharAt(1, 'i');
        sb.setLength(2);

        System.out.println("buffer dopo = " + sb);
        System.out.println("charAt(1) dopo = " + sb.charAt(1));
    }

}

Qui di seguito è riportato l'output prodotto dal programma:

buffer prima = Ciao
charAt(1) prima = i
buffer dopo = Ci
charAt(1) dopo = i

Il metodo getChars

Per copiare una sottostringa di un StringBuffer in un array, utilizziamo il metodo getChars(). Ha questa forma generale:

void getChars(int inizioSorgente,
              int fineSorgente,
              char[] destinazione,
              int inizioDestinazione)

Qui, inizioSorgente specifica l'indice dell'inizio della sotto-stringa, e fineSorgente specifica un indice che è uno oltre la fine della sotto-stringa desiderata. Questo significa che la sotto-stringa contiene i caratteri da inizioSorgente fino a fineSorgente–1. L'array che riceverà i caratteri è specificato da destinazione. L'indice all'interno di destinazione al quale la sotto-stringa sarà copiata è passato in inizioDestinazione. Bisogna prestare attenzione ad assicurarsi che l'array destinazione sia abbastanza grande da contenere il numero di caratteri nella sotto-stringa specificata.

Il metodo append

Il metodo append() concatena la rappresentazione stringa di qualsiasi altro tipo di dato alla fine dell'oggetto StringBuffer che lo invoca. Ha diverse versioni sovraccaricate. Ecco alcune delle sue forme:

StringBuffer append(String str)
StringBuffer append(int num)
StringBuffer append(Object obj)

Prima, viene ottenuta la rappresentazione stringa di ciascun parametro. Poi, il risultato viene aggiunto all'oggetto StringBuffer corrente. Il buffer stesso viene restituito da ogni versione di append(). Questo permette di concatenare chiamate successive, come mostrato nell'esempio seguente:

// Dimostra append().
class DemoAppend {

    public static void main(String[] args) {
        String s;
        int a = 42;
        StringBuffer sb = new StringBuffer(40);
        s = sb.append("a = ").append(a).append("!").toString();
        System.out.println(s);
    }

}

L'output di questo esempio è mostrato qui:

a = 42!

Il metodo insert

Il metodo insert() inserisce una stringa in un'altra. È sovraccaricato per accettare valori di tutti i tipi primitivi, più String, Object e CharSequence. Come append(), ottiene la rappresentazione stringa del valore con cui viene chiamato. Questa stringa viene quindi inserita nell'oggetto StringBuffer che invoca il metodo. Queste sono alcune delle sue forme:

StringBuffer insert(int indice, String str)
StringBuffer insert(int indice, char ch)
StringBuffer insert(int indice, Object obj)

Qui, indice specifica l'indice nel punto in cui la stringa verrà inserita nell'oggetto StringBuffer che invoca il metodo.

Il seguente programma di esempio inserisce "piace " tra "A me" e "Java!" all'interno di un oggetto StringBuffer:

// Dimostra insert().

class DemoInsert {

    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("A me Java!");
        sb.insert(2, "piace ");
        System.out.println(sb);
    }

}

L'output di questo esempio è mostrato qui:

A me piace Java!

Il metodo reverse

È possibile invertire i caratteri all'interno di un oggetto StringBuffer utilizzando reverse(), mostrato qui:

StringBuffer reverse()

Questo metodo restituisce l'inverso dell'oggetto su cui è stato chiamato. Il seguente programma dimostra reverse():

// Utilizzo di reverse() per invertire un StringBuffer.
class DemoInverti {

    public static void main(String[] args) {
        StringBuffer s = new StringBuffer("abcdef");
        System.out.println(s);
        s.reverse();
        System.out.println(s);
    }

}

Ecco l'output prodotto dal programma:

abcdef
fedcba

I metodi delete e deleteCharAt

È possibile eliminare caratteri all'interno di un StringBuffer utilizzando i metodi delete() e deleteCharAt(). Questi metodi sono mostrati qui:

StringBuffer delete(int indiceInizio, int indiceFine)
StringBuffer deleteCharAt(int posizione)

Il metodo delete() elimina una sequenza di caratteri dall'oggetto che lo invoca. Qui, indiceInizio specifica l'indice del primo carattere da rimuovere, e indiceFine specifica un indice oltre l'ultimo carattere da rimuovere. Quindi, la sotto-stringa eliminata va da indiceInizio a indiceFine–1. L'oggetto StringBuffer risultante viene restituito.

Il metodo deleteCharAt() elimina il carattere all'indice specificato da posizione. Restituisce l'oggetto StringBuffer risultante.

Ecco un programma che dimostra i metodi delete() e deleteCharAt():

// Dimostra delete() e deleteCharAt()
class DemoEliminazione {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Questo è un test.");
        sb.delete(4, 7);
        System.out.println("Dopo delete: " + sb);
        sb.deleteCharAt(0);
        System.out.println("Dopo deleteCharAt: " + sb);
    }
}

Il seguente output viene prodotto:

Dopo delete: Quesè un test.
Dopo deleteCharAt: uesè un test.

Il metodo replace

È possibile sostituire un insieme di caratteri con un altro insieme all'interno di un oggetto StringBuffer chiamando replace(). La sua firma è mostrata qui:

StringBuffer replace(int indiceInizio, int indiceFine, String str)

La sotto-stringa da sostituire è specificata dagli indici indiceInizio e indiceFine. Pertanto, la sotto-stringa da indiceInizio fino a indiceFine–1 viene sostituita. La stringa di sostituzione è passata in str. Viene restituito l'oggetto StringBuffer risultante.

Il seguente programma dimostra replace():

// Dimostra replace()
class DemostraReplace {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Questo è un test.");
        sb.replace(7, 8, "era");
        System.out.println("Dopo replace: " + sb);
    }
}

Di seguito è mostrato l'output prodotto dal programma:

Dopo replace: Questo era un test.

Il metodo substring

È possibile ottenere una porzione di un StringBuffer chiamando substring(). Ha le seguenti due forme:

String substring(int indiceInizio)
String substring(int indiceInizio, int indiceFine)

La prima forma restituisce la sotto-stringa che inizia a indiceInizio e arriva fino alla fine dell'oggetto StringBuffer invocante. La seconda forma restituisce la sotto-stringa che inizia a indiceInizio e arriva fino a indiceFine–1. Questi metodi funzionano proprio come quelli definiti per String che sono stati descritti in precedenza.

Alcuni metodi aggiuntivi di StringBuffer

Oltre ai metodi appena descritti, StringBuffer ne fornisce altri. Diversi sono riassunti nella seguente tabella:

Metodo Descrizione
StringBuffer appendCodePoint(int ch) Aggiunge un punto di codice Unicode alla fine dell'oggetto invocante. Viene restituito un riferimento all'oggetto.
int codePointAt(int i) Restituisce il punto di codice Unicode nella posizione specificata da i.
int codePointBefore(int i) Restituisce il punto di codice Unicode nella posizione che precede quella specificata da i.
int codePointCount(int inizio, int fine) Restituisce il numero di punti di codice nella porzione della String invocante che sono tra inizio e fine–1.
int indexOf(String str) Cerca nella StringBuffer invocante la prima occorrenza di str. Restituisce l'indice della corrispondenza, o –1 se non viene trovata alcuna corrispondenza.
int indexOf(String str, int indiceInizio) Cerca nella StringBuffer invocante la prima occorrenza di str, iniziando da indiceInizio. Restituisce l'indice della corrispondenza, o –1 se non viene trovata alcuna corrispondenza.
int lastIndexOf(String str) Cerca nella StringBuffer invocante l'ultima occorrenza di str. Restituisce l'indice della corrispondenza, o –1 se non viene trovata alcuna corrispondenza.
int lastIndexOf(String str, int indiceInizio) Cerca nella StringBuffer invocante l'ultima occorrenza di str, iniziando da indiceInizio. Restituisce l'indice della corrispondenza, o –1 se non viene trovata alcuna corrispondenza.
int offsetByCodePoints(int inizio, int num) Restituisce l'indice all'interno della stringa invocante che è num punti di codice oltre l'indice di partenza specificato da inizio.
CharSequence subSequence(int indiceInizio, int indiceFine) Restituisce una sottostringa della stringa invocante, iniziando da indiceInizio e fermandosi a indiceFine. Questo metodo è richiesto dall'interfaccia CharSequence, che è implementata da StringBuffer.
void trimToSize() Richiede che la dimensione del buffer di caratteri per l'oggetto invocante sia ridotta per adattarsi meglio al contenuto corrente.
Tabella 1: Tabella che riassume altri metodi di StringBuffer

Il seguente programma dimostra indexOf() e lastIndexOf():

class DemoIndexOf {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("uno due uno");
        int i;
        i = sb.indexOf("uno");
        System.out.println("Primo indice: " + i);
        i = sb.lastIndexOf("uno");
        System.out.println("Ultimo indice: " + i);
    }
}

L'output è mostrato qui:

Primo indice: 0
Ultimo indice: 8