Quote Originariamente inviata da Gas75 Visualizza il messaggio
ho notato uno strano comportamento del metodo capacity() di StringBuilder...
La capacity non è il numero "logico" di caratteri (cioè la lunghezza della stringa risultante). Invece è la lunghezza fisica (arr.length) dell'array interno di char[]. StringBuffer/StringBuilder funzionano a capacità più espansa rispetto alla lunghezza logica.

Se inserendo caratteri la capacità ad un certo punto non è più sufficiente, deve essere istanziato un nuovo array char[], devono essere copiati tutti i caratteri dal vecchio al nuovo array e poi il nuovo array sostituisce quello vecchio (che finirà in pasto al garbage collector).

Il punto è che la espansione non avviene esattamente del minimo necessario ma di più. Se la capacity è 10, finché inserisci 10 caratteri, ok. Se ne inserisci ancora un altro, la capacity 10 non è più sufficiente. La classe NON rialloca a 11 ma di più.
Nel sorgente di AbstractStringBuilder (base di StringBuffer/StringBuilder), si può vedere

codice:
    void expandCapacity(int minimumCapacity) {
        int newCapacity = value.length * 2 + 2;
        if (newCapacity - minimumCapacity < 0)
            newCapacity = minimumCapacity;
.....

Se capacity attuale è 10 e internamente chiede expandCapacity(11), la nuova capacity è 10*2+2 = 22.

Questo ha un grosso vantaggio: le riallocazioni non avvengono ogni momento ma solo ogni tanto. Insomma lo spreco di tempo per riallocazione-copia si dice che è "ammortizzato" nel tempo.

Le collezioni come ArrayList/Vector usano esattamente lo STESSO approccio nella gestione del loro array interno.