2011-11-04 8 views
20

Era una domanda di intervista. Mi è stato chiesto di implementare la funzione di aggiunta StringBuffer. Ho visto il codice dopo l'intervista. Ma non riesco a capire come viene eseguita l'operazione con la creazione di un singolo oggetto.In che modo StringBuffer implementa la funzione di accodamento senza creare due oggetti?

Sto pensando così.

String s = "orange"; 
s.append("apple"); 

Qui vengono creati due oggetti.

Ma

StringBuilder s = new StringBuilder("Orange"); 
s.append("apple"); 

Ora qui viene creato un solo oggetto.

In che modo Java esegue questa operazione?

+0

Ci sono alcune ipotesi in questione che non sono corretti. 'new StringBuilder()' e 'new String()' crea due oggetti. –

+3

Era la mia domanda? ;) –

risposta

45

In primo luogo c'è un problema con la tua domanda:

String s = "orange"; 
s.append("apple"); 

qui due oggetti vengono creati

corretta, vengono creati due oggetti, la stringa "arancia" e la stringa "mele ", all'interno di StringBuffer/StringBuilder non verrà creato alcun oggetto se non si verifica un overflow del buffer. Quindi quelle linee di codice creano 2 o 3 oggetti.

StringBuilder s = new StringBuilder("Orange"); 
s.append("apple"); 

Ora qui solo un oggetto viene creato

Non so dove si ottiene che, qui si crea un oggetto StringBuilder, una stringa "Orange", una "mela" String , per un totale di 3 oggetti, o 4 se si trabocca il buffer StringBuilder. (Conto la creazione dell'array come creazione dell'oggetto).


ho letto la tua domanda come, come può fare lo StringBuilder accodamento senza creare un nuovo oggetto (quando il buffer non è sorvolato)?

Si dovrebbe guardare StringBuilder, poiché è l'implementazione non thread-safe.Il codice è interessante e facile da leggere. Ho aggiunto i commenti in linea.

Come struttura interna c'è un array di caratteri, non una stringa. Inizialmente è costruito con lunghezza 16 e verrà aumentato ogni volta che la capacità viene superata. Se le stringhe da aggiungere rientrano nell'array char, non è necessario creare nuovi oggetti.

StringBuilder estende AbstractStringBuilder, dove troverete il seguente codice:

/** 
* The value is used for character storage. 
*/ 
char value[]; 

Poiché non tutti l'array verrà utilizzato in un dato momento, un'altra variabile importante è la lunghezza:

/** 
* The count is the number of characters used. 
*/ 
int count; 

Ci sono molti sovraccarichi di append, ma il più interessante è il seguente:

public AbstractStringBuilder append(String str) { 
    if (str == null) str = "null"; //will literally append "null" in case of null 
    int len = str.length(); //get the string length 
    if (len == 0) return this; //if it's zero, I'm done 
    int newCount = count + len; //tentative new length 
    if (newCount > value.length) //would the new length fit? 
     expandCapacity(newCount); //oops, no, resize my array 
    str.getChars(0, len, value, count); //now it will fit, copy the chars 
    count = newCount; //update the count 
    return this; //return a reference to myself to allow chaining 
} 

String.getChars (int srcBegin, int srcEnd, char [] dst, int dstBegin) Copia i caratteri da questa stringa nell'array di caratteri di destinazione.

Così, il metodo append è abbastanza semplice, l'unica magia sinistra per scoprire è il expandCapacity, eccolo:

void expandCapacity(int minimumCapacity) { 
    //get the current length add one and double it 
    int newCapacity = (value.length + 1) * 2; 
    if (newCapacity < 0) { //if we had an integer overflow 
     newCapacity = Integer.MAX_VALUE; //just use the max positive integer 
    } else if (minimumCapacity > newCapacity) { //is it enough? 
     //if doubling wasn't enough, use the actual length computed 
     newCapacity = minimumCapacity; 
    } 
    //copy the old value in the new array 
    value = Arrays.copyOf(value, newCapacity); 
} 

Arrays.copyOf (char [] originali, int newLength) copia il array specificato, troncamento o riempimento con caratteri null (se necessario) in modo che la copia abbia la lunghezza specificata.

Nel nostro caso, imbottitura, poiché stiamo espandendo la lunghezza.

+3

puoi spiegare perché in expandCapacity, first value.length viene aumentato di 1 e quindi moltiplicato per 2? È l'incremento di 1 richiesto per tenere conto del carattere null – CyprUS

4

String è immutabile. L'aggiunta di una stringa può generare solo una nuova stringa.

StringBuilder è modificabile. L'aggiunta a StringBuilder è un'operazione in-place, come l'aggiunta a un ArrayList.

+0

Ciao Slaks, lo so. Voglio sapere come sta facendo il costruttore di stringhe. – javaMan

2

StringBuffer, come StringBuilder alloca una matrice di caratteri in cui copia le stringhe aggiunte. Crea solo nuovi oggetti quando il numero di caratteri supera la dimensione dell'array, nel qual caso rialloca e copia l'array.

1

StringBuilder è in possesso di un buffer di char s in un char[] e li converte in String quando toString è chiamato.

3

Questo non viene compilato.

String S= "orange"; 
S.append("apple"); 

se si fa

final String S= "orange"; 
final S2 = S + "apple"; 

Questo non crea alcun oggetto in quanto è ottimizzato al momento della compilazione di due stringhe letterali.

StringBuilder s = new StringBuilder("Orange"); 
s.append("apple"); 

Questo crea due oggetti StringBuilder e char[] avvolge. Se si utilizza

String s2 = s.toString(); 

Questo crea altri due oggetti.

Se fai

String S= "orange"; 
S2 = S + "apple"; 

Questo è lo stesso

String S2 = new StringBuilder("orange").append("apple").toString(); 

che crea 2 + 2 = 4 oggetti.

0

Come altri descritti, StringBuffer è modificabile e viene implementato utilizzando un array char. Le operazioni nel StringBuffer sono operazioni sul posto.

Maggiori informazioni possono essere disponibili dal seguente collegamento http://www.concentric.net/~ttwang/tech/jfastbuf.htm

Essa mostra semplici implementazioni StringBuffer utilizzando una matrice char.

2
String s = "orange"; 
s.append("apple"); 

non è corretto perché il metodo append non è disponibile in stringa:

-1
****String s1="Azad"; ----One object will create in String cons. pool 

System.out.println(s1);--output--Azad 

s1=s1.concat("Raja"); Two object will create 1-Raja,2-AzadRaja and address of AzadRaja Store in reference s1 and cancel ref.of Azad object 

System.out.println(s1); --output AzadRaja**** 
+0

La risposta è molto difficile da leggere. Aggiunge informazioni utili che non sono già contenute nella risposta accettata? –

1

tl; dr: In parole semplici, ogni concatenazione di stringhe espressione usando il carattere + porta ad un nuovo oggetto String con i contenuti delle stringhe iniziali copiati nella nuova. StringBuffer contiene una struttura interna che si espande solo quando è necessario, a cui i caratteri vengono aggiunti.

Ehi, ma molte persone usano la concatenazione di stringhe +!

Beh, noi/loro non dovrebbero.

In termini di utilizzo della memoria, si utilizza un array in StringBuffer al fine di contenere i caratteri - che ridimensiona, di verità, ma raramente se l'algoritmo applicato in ridimensionamento è efficiente, e solo un String oggetto che è creato quando toString() è chiamato, molto meglio della creazione di un nuovo oggetto String su ciascuna concatenazione +.

In termini di tempo complessità, i caratteri vengono copiati una sola volta dal _chars alla nuova stringa (O(n) tempo complessità), che in genere è necessario meglio di concatenazione di stringhe utilizzando l'operatore +, in cui ogni operazione porta ad una nuova copia dei personaggi a un nuovo oggetto, che porta alle operazioni O(1 + 2 + .... + n) = O(n^2).

Devo implementare uno per conto mio?

Sarebbe bene per te in termini di esercizio, ma i linguaggi moderni forniscono implementazioni native StringBuffer per usarlo nel codice di produzione.

In quattro semplici passaggi:

  1. creare una classe MyCustomStringBuilder che internamente (in privato) detiene una matrice (Diamo il nome _chars) di caratteri di una dimensione iniziale fissa. Questo array manterrà i caratteri di stringa.
  2. Aggiungere un metodo in espansione che aumenterà la dimensione di _chars volta nell'azienda lunghezza dei caratteri stringa supera la sua lunghezza. (Quello che sta praticamente facendo, sta attuando una semplice versione di un ArrayList internamente).
  3. Quando si utilizza il metodo stringBufferInstance.append(String s), aggiungere caratteri a _chars, aumentandone le dimensioni se necessario.
  4. Nell'implementazione metodo toString(), si può semplicemente creare un string using the array:

    public String toString() { 
        return new String(_chars); 
    } 
    
Problemi correlati