2010-02-11 16 views
91

Jak wyczyścić bufor łańcuchowy w Javie po pętli, aby następna iteracja używała czystego bufora ciągów?Czyszczenie bufora ciągów/budowania po pętli

+2

Kolejne pytanie: dlaczego używasz SB tylko dla jednej iteracji pętli? Czy jest kolejna wewnętrzna iteracja? SB nie jest warta, jeśli po prostu chcesz zrobić A + B + C + D (kompilator Java będzie wewnętrznie używać SB). Pomaga, jeśli chcesz warunkowo dodać części ciągów, ale poza tym ... po prostu użyj "+". – helios

+0

You madarchod conajmniej zaakceptować odpowiedź –

Odpowiedz

111

Jedną z opcji jest użycie metody usuwania następująco:

StringBuffer sb = new StringBuffer(); 
for (int n = 0; n < 10; n++) { 
    sb.append("a"); 

    // This will clear the buffer 
    sb.delete(0, sb.length()); 
} 

Inną opcją (nieco czystsze) wykorzystuje setLength (int len):

sb.setLength(0); 

Zobacz Javadoc o więcej informacji:

+15

Coś nieco mniej śmieci byłoby po prostu zadeklarować StringBuffer wewnątrz pętli. –

+9

Ah, myślę, że sb.setLength (0); jest czystszy i bardziej wydajny niż deklarowanie go w pętli. Twoje rozwiązanie jest sprzeczne z korzyściami płynącymi z używania StringBuffer ... – Jon

+4

Myślę, że korzyści związane z wydajnością wynikają z możliwości zmiany łańcucha znaków, a nie z zapisywania instancji. oto krótki test iteracji 1e8: pętla wewnętrzna (2.97s): http://ideone.com/uyyTL14w, pętla zewnętrzna (2,87s): http://ideone.com/F9lgsIxh –

5
buf.delete(0, buf.length()); 
5

Proponuję kreatynę g nowy StringBuffer (lub jeszcze lepiej, StringBuilder) dla każdej iteracji. Różnica w wydajności jest naprawdę znikoma, ale twój kod będzie krótszy i prostszy.

+0

Ponieważ java jest obecnie najczęściej używana na Androidzie, nie jestem pewien, czy przydzielenie nowego obiektu w pętli jest dobrą praktyką dla wydajności i żywotności baterii. Złożoność kodu dodana przez wyczyszczenie 'StringBuilder' jest minimalna w porównaniu do potencjalnego przyrostu wydajności. –

+1

Jeśli masz jakiekolwiek dowody takiej różnicy w wydajności, udostępnij je. (Będę również zadowolony, gdy zobaczysz statystyki miejsc, w których Java jest najczęściej używana i pod jaką definicją "głównie".) –

+1

Dobrze wiadomo, że alokacja (nowe słowo kluczowe w Javie) jest droższa niż zmiana niektórych pól tego samego obiekt. W przypadku "przeważnie", z którym można się bardzo dobrze wymieniać, istnieje ponad 1,5 miliarda urządzeń z Androidem, wszystkie wykorzystują Javę. –

39

Najprostszym sposobem na ponowne wykorzystanie StringBuffer jest użycie metody setLength()

public void setLength(int newLength)

może mieć sprawę jak

StringBuffer sb = new StringBuffer("HelloWorld"); 
// after many iterations and manipulations 
sb.setLength(0); 
// reuse sb 
+2

@MMahmoud, W przykładowym kodzie powinien odczytać 'setLength' zamiast' setlength'. – OnaBai

0
StringBuffer sb = new SringBuffer(); 
// do something wiht it 
sb = new StringBuffer(); 

myślę, że ten kod jest szybciej.

+2

To będzie miało problemy z wydajnością. Tworzy nowy obiekt po każdej iteracji. –

+0

@AdityaSingh Jest to całkowicie rozsądne podejście. Nie zakładaj problemów z wydajnością bez dowodów. – shmosel

13

Masz dwie opcje:

użyć:

sb.setLength(0); // It will just discard the previous data, which will be garbage collected later. 

lub użyj:

sb.delete(0, sb.length()); // A bit slower as it is used to delete sub sequence. 

UWAGA

Unikaj deklarowania StringBuffer lub StringBuilder obiektów wewnątrz pętli innego to będzie tworzyć nowe obiekty przy każdej iteracji. Tworzenie obiektów wymaga zasobów systemowych, przestrzeni, a także zabiera czas. Dlatego na dłuższą metę unikaj deklarowania ich w pętli, jeśli to możliwe.

0

Już dobra odpowiedź tam. Wystarczy dodać wynik testu wydajności dla StringBuffer i różnicę wydajności StringBuild użyć nowej instancji w pętli lub użyć pętli setLength (0).

Podsumowanie brzmi: W dużej pętli

  • StringBuilder jest znacznie szybsze niż StringBuffer
  • Tworzenie nowej instancji StringBuilder w pętli nie mają różnicę setlength (0). (Setlength (0) posiadają bardzo bardzo małe korzyści nie tworzyć nową instancję).
  • StringBuffer jest mniejsza niż StringBuilder przez tworzenie nowych wystąpienie w pętli
  • setLength (0) o StringBuffer jest bardzo wolniej niż tworzyć nową instancję w pętli.

Bardzo proste odniesienia (po prostu ręcznie zmieniony kod i zrobić inny test):

public class StringBuilderSpeed { 
public static final char ch[] = new char[]{'a','b','c','d','e','f','g','h','i'}; 

public static void main(String a[]){ 
    int loopTime = 99999999; 
    long startTime = System.currentTimeMillis(); 
    StringBuilder sb = new StringBuilder(); 
    for(int i = 0 ; i < loopTime; i++){ 
     for(char c : ch){ 
      sb.append(c); 
     } 
     sb.setLength(0); 
    } 
    long endTime = System.currentTimeMillis(); 
    System.out.println("Time cost: " + (endTime - startTime)); 
} 

}

New StringBuilder instancja w pętli: koszt Czas: 3693, 3862, 3624, 3742

StringBuilder setlength: Czas koszt: 3465, 3421, 3557, 3408

New StringBuffer instancja w pętli: Czas Koszt: 8327, 8324, 8284

StringBuffer setlength Czas koszt: 22878, 23017, 22894

Ponownie StringBuilder setlength aby zapewnić nie moja labtop dostałem jakiś problem używać takich długo StringBuffer setlength :-) kosztów Czas: 3448

1
public void clear(StringBuilder s) { 
    s.setLength(0); 
} 

Zastosowanie:

StringBuilder v = new StringBuilder(); 
clear(v); 

dla czytelności, myślę, że jest to najlepsze rozwiązanie.