2012-11-28 11 views
5

Sto facendo un parsing xml e faccio una stringa replaceAll che utilizza un'enorme quantità di spazio di memoria come mostrato nell'immagine qui sotto.La stringa sostituisce utilizzando un enorme spazio heap

Codice va come:

private final String getText() { 
    // special handling for apostrophe encoding 
    // site will expect both ' , ' and %27. 
    // change %27 or 'or ' to ' 
    return _text.toString().trim().replaceAll("'", "'") 
      .replaceAll("'", "'").replaceAll("%27", "'"); 
} 

Il metodo getText() è spesso chiamata dal endElement() metodo SAXParser.

Qualcuno può suggerire come si fa a cambiare questa funzionalità che utilizzerà meno spazio di heap

! [Trace] [1]

+0

stai che fare con enormi nodi di testo nel vostro XML? – jtahlborn

risposta

3

L'utilizzo di espressioni regolari per la sostituzione di stringhe semplici come questa è troppo costoso. Vorrei semplicemente costruire un'istanza di StringBuilder come questo:

StringBuilder sb = new StringBuilder(); 

while (not end of _text) { 
    find next '&' 
    if the next substring is in (' ') etc. 
    append the prev portion of _text to sb 
    append replacement char 
    set the beginning of the chunk to the next char 
} 
return sb.toString(); 
1

Il tuo metodo replaceAll viene chiamato su un String, che è immutabile. Per questo motivo, una nuova stringa deve essere creata ogni volta che la si modifica (3 volte in questo caso). Se si utilizza invece una StringBuilder, la stringa sarà modificabile e non è necessario assegnarla di nuovo ogni volta che si sostituisce qualcosa.

A proposito, non c'è "sostituire" che tu abbia bisogno di StringBuilders, quindi dovrete usare indexOf più volte per trovare la stringa di offendere, e replace sui risultati. trim() è lì.

3

Dal _text è già un StringBuffer è possibile utilizzare indexOf(String str) e replace(int start, int end, String str). In questo modo non creerai affatto oggetti temporanei String.

Utilizzando una funzione come:

private void replace(StringBuffer buff,String toReplace,String replaceTo){ 
int start; 
while ((start=buff.indexOf(toReplace))>=0) 
    buff.replace(start,start+toReplace.length(),replaceTo); 
} 

e chiamare la funzione in te getText(), per ogni combinazione, come:

String replaceTo=","; 
replace(_text,"'",replaceTo); 
replace(_text,"'",replaceTo); 
replace(_text,"%27",replaceTo); 
return _text.toString(); 
+0

Esattamente quello di cui avevo bisogno. Grazie. –

1

Si può fare tutte le 3 sostituzioni in un colpo solo, come

text.replaceAll("('|&39;|%27)", "'"); 

è fino a 3 volte più efficiente di 3 sostituzioni consecutive, dal momento che ogni sostituzione può creare una nuova stringa

1

Dal momento che si stanno ottenendo il testo in SAX deve venire da qui

characters(char[] ch, int start, int length) 

è necessario salvare questi argomenti nei campi, e endElement() è possibile fare la sostituzione come

StringBuilder sb = new StringBuilder(); 
    for (int i = start; i < length; i++) { 
       // %27 
     if (ch[i] == '%' && length - i > 2 && ch[i + 1] == '2' && ch[i + 2] == '7') { 
         sb.append('\''); 
      i += 2; 
       // &apos; 
       } else if (
        ... 
       // &#39; 
       } else if (
        ... 
     } else { 
      sb.append(ch[i]); 
     } 
    } 
    String res = sb.toString(); 

il codice è lungo ma molto efficiente, è anche possibile aggiungere rifilatura

Problemi correlati