quante stringhe vengono create in memoria quando si concatenano le stringhe in Java?

17

Mi è stato chiesto delle stringhe immutabili in Java. Mi è stato assegnato il compito di scrivere una funzione che concatenasse un numero di "a" a una stringa.

Quello che ho scritto:

public String foo(int n) {
    String s = "";
    for (int i = 0; i < n; i++) {
        s = s + "a"
    }
    return s;
}

Mi è stato poi chiesto quante stringhe questo programma avrebbe generato, supponendo che la garbage collection non si verificasse. I miei pensieri per n = 3 erano

  1. ""
  2. "a"
  3. "a"
  4. "aa"
  5. "a"
  6. "aaa"
  7. "a"

In pratica, vengono create 2 stringhe in ogni iterazione del ciclo. Tuttavia, la risposta era n 2 . Quali stringhe verranno create in memoria da questa funzione e perché è così?

    
posta ahalbert 27.11.2013 - 03:01
fonte

3 risposte

26

I was then asked how many strings this program would generate, assuming garbage collection does not happen. My thoughts for n=3 was (7)

Le stringhe 1 ( "" ) e 2 ( "a" ) sono le costanti nel programma, non sono create come parte delle cose ma sono "internate" perché sono costanti a conoscenza del compilatore. Ulteriori informazioni su questo argomento sono disponibili all'indirizzo Internazioni di stringhe su Wikipedia.

Rimuove anche le stringhe 5 e 7 dal conteggio poiché sono lo stesso "a" di String # 2. Questo lascia le stringhe # 3, # 4 e # 6. La risposta è "3 stringhe sono create per n = 3" usando il tuo codice.

Il conteggio di n 2 è ovviamente sbagliato perché in n = 3, questo sarebbe 9 e anche nella tua peggiore risposta, era solo 7. Se le tue stringhe non internate erano corrette, la risposta dovrebbe essere stata 2n + 1.

Quindi, la domanda su come dovrebbe fare questo?

Poiché String è immutabile , vuoi una cosa mutabile - qualcosa che puoi cambiare senza creare nuovi oggetti. Questo è il StringBuilder .

La prima cosa da guardare sono i costruttori. In questo caso sappiamo per quanto tempo sarà la stringa, e c'è un costruttore StringBuilder(int capacity) che significa che assegniamo esattamente quanto ci serve.

Successivamente, "a" non deve necessariamente essere una Stringa , ma può essere un carattere 'a' . Questo ha un lieve incremento delle prestazioni quando si chiama append(String) rispetto a append(char) - con append(String) , il metodo deve scoprire quanto a lungo è la stringa e lavorare su quello. D'altra parte, char ha sempre esattamente un carattere.

Le differenze di codice possono essere visualizzate su StringBuilder.append (String) rispetto a StringBuilder.append (char) . Non è qualcosa di cui essere too interessato, ma se stai cercando di impressionare il datore di lavoro è meglio usare le migliori pratiche possibili.

Quindi, come appare quando lo metti insieme?

public String foo(int n) {
    StringBuilder sb = new StringBuilder(n);
    for (int i = 0; i < n; i++) {
        sb.append('a');
    }
    return sb.toString();
}

Sono stati creati un StringBuilder e una stringa. Nessuna stringa aggiuntiva necessaria per essere internata.

Scrivi altri programmi semplici in Eclipse. Installa pmd ed eseguilo sul codice che scrivi. Nota cosa si lamenta e aggiusta quelle cose. Avrebbe trovato la modifica di una stringa con + in un ciclo, e se l'avessi modificata in StringBuilder, avrebbe forse trovato la capacità iniziale, ma avrebbe sicuramente catturato la differenza tra .append("a") e .append('a')

    
risposta data 27.11.2013 - 04:39
fonte
9

In ogni iterazione, viene creato un nuovo String dall'operatore + e assegnato a s . Dopo il ritorno, tutti tranne l'ultimo vengono raccolti.

Le costanti di stringa come "" e "a" non vengono create ogni volta, queste sono stringhe internate . Poiché le stringhe sono immutabili, possono essere liberamente condivise; questo succede alle costanti di stringa.

Per concatenare in modo efficiente le stringhe, utilizza StringBuilder .

    
risposta data 27.11.2013 - 03:28
fonte
4

Come MichaelT spiega nella sua risposta, il tuo codice alloca le stringhe O (n). Ma assegna anche O (n 2 ) byte di memoria e funziona nel tempo O (n 2 ).

Alloca i byte O (n 2 ), perché le stringhe che stai allocando hanno lunghezze 0, 1, 2, ..., n-1, n, che somme a (n 2 + n) / 2 = O (n 2 ).

Anche il tempo è O (n 2 ), perché l'allocazione della stringa i-es richiede la copia della stringa (i-1) -th, che ha lunghezza i-1. Ciò significa che ogni byte assegnato deve essere copiato, il che richiederà tempo O (n 2 ).

Forse questo è ciò che intendevano gli intervistatori?

    
risposta data 28.11.2013 - 21:39
fonte

Leggi altre domande sui tag