String, StringBuffer i StringBuilder
Proszę powiedz mi sytuację w czasie rzeczywistym, aby porównać String
, StringBuffer
, i StringBuilder
?
11 answers
Różnica Zmienności:
String
jest niezmienne, jeśli spróbujesz zmienić ich wartości, zostanie utworzony inny obiekt, podczas gdy StringBuffer
i StringBuilder
są mutowalne , aby mogły zmienić swoje wartości.
Thread-Safety Difference:
Różnica między StringBuffer
A StringBuilder
jest taka, że StringBuffer
jest bezpieczna dla wątku. Jeśli więc aplikacja musi być uruchomiona tylko w jednym wątku, to lepiej jest użyć StringBuilder
. StringBuilder
jest bardziej wydajny niż StringBuffer
.
Sytuacje:
- jeśli twój łańcuch znaków nie zmieni się, Użyj klasy łańcuchów, ponieważ obiekt
String
jest niezmienny. - jeśli twój ciąg znaków może się zmienić (przykład: wiele logiki i operacji w konstrukcji łańcucha) i będzie dostępny tylko z jednego wątku, użycie
StringBuilder
jest wystarczająco dobre. - jeśli twój ciąg znaków może się zmienić i będzie dostępny z wielu wątków, użyj
StringBuffer
PonieważStringBuffer
jest synchroniczny, więc masz gwint-bezpieczeństwo.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-19 21:26:24
- używasz
String
gdy odpowiednia jest niezmienna struktura; uzyskanie nowego ciągu znaków zString
może wiązać się z niedopuszczalną karą za wydajność, zarówno w czasie procesora, jak i w pamięci (uzyskanie podciągów jest wydajne, ponieważ dane nie są kopiowane, ale oznacza to, że potencjalnie dużo większa ilość danych może pozostać przydzielona). - używasz
StringBuilder
Kiedy trzeba utworzyć zmienną sekwencję znaków, zwykle w celu połączenia kilku sekwencji znaków razem. - używasz
StringBuffer
w tych samych okolicznościach można użyćStringBuilder
, ale gdy zmiany w łańcuchu muszą być zsynchronizowane (ponieważ kilka wątków odczytuje / modyfikuje bufor Łańcuchowy).
Zobacz przykład tutaj .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-03 14:33:06
Podstawy:
String
jest niezmienną klasą, nie można jej zmienić.
StringBuilder
jest zmienną klasą, do której można dodawać, zastępować lub usuwać znaki i ostatecznie konwertować na String
StringBuffer
jest oryginalną zsynchronizowaną wersją StringBuilder
Powinieneś preferować StringBuilder
we wszystkich przypadkach, w których dostęp do obiektu ma tylko jeden wątek.
Szczegóły:
Zauważ również, że StringBuilder/Buffers
nie są magiczne, po prostu używają tablicy jako backing object i ta tablica musi być ponownie przydzielona, gdy tylko się zapełni. Upewnij się, że Twoje obiekty StringBuilder/Buffer
są wystarczająco duże, aby nie musiały być stale zmieniane przy każdym wywołaniu .append()
.
StringBuilder/Buffer
zaczną rosnąć duży.
W Javie String x = "A" + "B";
używa StringBuilder
Za kulisami. Tak więc w prostych przypadkach nie ma korzyści z deklarowania własnej. Ale jeśli budujesz String
obiekty, które są duże, powiedzmy mniej niż 4K, deklarowanie StringBuilder sb = StringBuilder(4096);
jest o wiele bardziej efektywne niż konkatenacja lub użycie domyślnego konstruktora , który ma tylko 16 znaków. Jeśli twoja String
ma być mniejsza niż 10K, zainicjuj ją konstruktorem do 10K, aby było bezpieczne. Ale jeśli jest initialize do 10k to piszesz 1 znak większy niż 10K, zostanie ponownie przydzielony i skopiowany do tablicy 20k. Więc inicjalizacja wysokiego jest lepsza niż niskiego.
W przypadku automatycznej zmiany rozmiaru, na 17. znaku tablica zapasowa zostaje ponownie przydzielona i skopiowana do 32 znaków, na 33. znaku dzieje się to ponownie i można ponownie przydzielać i skopiować tablicę do 64 znaków. Możesz zobaczyć, jak to degeneruje się do partii re-alokacji i kopii, czego tak naprawdę starasz się uniknąć używając StringBuilder/Buffer
w miejsce.
To jest z kodu źródłowego JDK 6 dla AbstractStringBuilder
void expandCapacity(int minimumCapacity) {
int newCapacity = (value.length + 1) * 2;
if (newCapacity < 0) {
newCapacity = Integer.MAX_VALUE;
} else if (minimumCapacity > newCapacity) {
newCapacity = minimumCapacity;
}
value = Arrays.copyOf(value, newCapacity);
}
Najlepszą praktyką jest zainicjowanie StringBuilder/Buffer
trochę większego, niż myślisz, że będziesz potrzebował, jeśli nie wiesz od razu, jak duży będzie String
, ale możesz się domyślić. Jedna alokacja nieco więcej pamięci niż potrzebujesz będzie lepsza niż wiele ponownych alokacji i kopii.
Uważaj również na inicjalizację a StringBuilder/Buffer
z String
, ponieważ przydziela ona tylko rozmiar łańcucha + 16 znaków, co w większości przypadków po prostu rozpocznie zdegenerowany cykl re-alokacji i kopiowania, którego próbujesz uniknąć. Poniżej znajduje się kod źródłowy Java 6.
public StringBuilder(String str) {
super(str.length() + 16);
append(str);
}
Jeśli przypadkiem trafisz na instancję StringBuilder/Buffer
, której nie stworzyłeś i nie możesz kontrolować wywoływanego konstruktora, istnieje sposób na uniknięcie zdegenerowanego zachowania realokacji i kopiowania. Call .ensureCapacity()
z rozmiarem, który chcesz zapewnić wynik String
będzie pasować.
Alternatywy:
Tak dla przypomnienia, jeśli robisz naprawdę ciężkie String
Budowa i manipulacja, istnieje znacznie bardziej zorientowana na wydajność alternatywa o nazwie {77]} liny {40]}.
Inną alternatywą jest utworzenie implementacji StringList
przez podklasowanie ArrayList<String>
i dodanie liczników do śledzenia liczby znaków na każdej .append()
i innych operacji na liście, a następnie nadpisanie .toString()
, aby utworzyć StringBuilder
z listy. dokładny rozmiar, którego potrzebujesz, Pętla przez Listę i zbuduj wyjście, możesz nawet uczynić StringBuilder
zmienną instancji i "buforować" wyniki .toString()
i tylko ponownie wygenerować ją, gdy coś się zmieni.
Nie zapominaj również o String.format()
podczas budowania stałych, sformatowanych danych wyjściowych, które mogą być optymalizowane przez kompilator w miarę ich ulepszania.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-17 16:49:05
Masz na myśli konkatenację?
Przykład ze świata rzeczywistego: chcesz utworzyć nowy ciąg znaków spośród wielu innych.
Na przykład, aby wysłać wiadomość:
String
String s = "Dear " + user.name + "<br>" +
" I saw your profile and got interested in you.<br>" +
" I'm " + user.age + "yrs. old too"
StringBuilder
String s = new StringBuilder().append.("Dear ").append( user.name ).append( "<br>" )
.append(" I saw your profile and got interested in you.<br>")
.append(" I'm " ).append( user.age ).append( "yrs. old too")
.toString()
Lub
String s = new StringBuilder(100).appe..... etc. ...
// The difference is a size of 100 will be allocated upfront as fuzzy lollipop points out.
StringBuffer (składnia jest dokładnie taka jak w Stringbuilderze, efekty są różne)
O
StringBuffer
vs. StringBuilder
Pierwszy jest zsynchronizowany, a później nie.
Więc jeśli wywołanie go kilka razy w jednym wątku (co stanowi 90% przypadków), StringBuilder
uruchomi dużo {36]} szybciej, ponieważ nie zatrzyma się, aby sprawdzić, czy posiada blokadę wątku.
Dlatego zaleca się użycie StringBuilder
(o ile oczywiście nie masz dostępu do więcej niż jednego wątku w tym samym czasie, co jest rzadkością)
String
concatenation (using the + operator ) may be optimized by the compiler to use StringBuilder
Under, so, it not longer something to worry about, in The elder days of Java, to było coś, co wszyscy mówią, że należy unikać za wszelką cenę, ponieważ każda konkatenacja tworzy nowy obiekt String. Nowoczesne Kompilatory już tego nie robią, ale nadal dobrą praktyką jest używanie StringBuilder
zamiast tego na wypadek, gdybyś używał "starego" kompilatora.
Edit
Tylko dla ciekawskich, to jest to, co kompilator robi dla tej klasy:
class StringConcatenation {
int x;
String literal = "Value is" + x;
String builder = new StringBuilder().append("Value is").append(x).toString();
}
Javap-C StringConcatenation
Compiled from "StringConcatenation.java"
class StringConcatenation extends java.lang.Object{
int x;
java.lang.String literal;
java.lang.String builder;
StringConcatenation();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: aload_0
5: new #2; //class java/lang/StringBuilder
8: dup
9: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V
12: ldc #4; //String Value is
14: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
17: aload_0
18: getfield #6; //Field x:I
21: invokevirtual #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
24: invokevirtual #8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
27: putfield #9; //Field literal:Ljava/lang/String;
30: aload_0
31: new #2; //class java/lang/StringBuilder
34: dup
35: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V
38: ldc #4; //String Value is
40: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
43: aload_0
44: getfield #6; //Field x:I
47: invokevirtual #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
50: invokevirtual #8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
53: putfield #10; //Field builder:Ljava/lang/String;
56: return
}
Linie numerowane 5 - 27 są dla łańcuch o nazwie "literal"
Linie numerowane 31-53 są dla Ciągu o nazwie "builder"
Nie ma żadnej różnicy, dokładnie ten sam kod jest wykonywany dla obu łańcuchów.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-04 16:47:34
---------------------------------------------------------------------------------- String StringBuffer StringBuilder ---------------------------------------------------------------------------------- Storage Area | Constant String Pool Heap Heap Modifiable | No (immutable) Yes( mutable ) Yes( mutable ) Thread Safe | Yes Yes No Performance | Fast Very slow Fast ----------------------------------------------------------------------------------
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-26 13:50:41
String
The String class
reprezentuje ciągi znaków. Wszystkie literały znaków w programie Java, takie jak "abc"
są implementowane jako instancje tej klasy.
Obiekty String są niezmienne po ich utworzeniu nie możemy ich zmienić. (ciągi są stałymi )
-
Jeśli Łańcuch znaków jest tworzony za pomocą konstruktora lub metody, to łańcuchy te będą przechowywane w pamięć sterty jak również
SringConstantPool
. Ale przed zapisaniem w Puli wywołujeintern()
metoda sprawdzania dostępności obiektów z tą samą zawartością w puli przy użyciu metody equals. jeśli String-copy jest dostępny w Puli, to zwraca referencję. W przeciwnym razie obiekt String jest dodawany do puli i zwraca referencję.- język Java zapewnia specjalne Wsparcie dla operatora concatenation string (
+
) oraz dla konwersji innych obiektów za sznurki. String concatenation jest zaimplementowany za pomocą klasy StringBuilder(lub StringBuffer) i jej metody append.
String heapSCP = new String("Yash"); heapSCP.concat("."); heapSCP = heapSCP + "M"; heapSCP = heapSCP + 777; // For Example: String Source Code public String concat(String str) { int otherLen = str.length(); if (otherLen == 0) { return this; } int len = value.length; char buf[] = Arrays.copyOf(value, len + otherLen); str.getChars(buf, len); return new String(buf, true); }
- język Java zapewnia specjalne Wsparcie dla operatora concatenation string (
-
Literały łańcuchów są przechowywane w
StringConstantPool
.String onlyPool = "Yash";
StringBuffer i StringBuffer są zmiennymi sekwencjami znaków. Oznacza to, że można zmienić wartość tego obiektu. StringBuffer ma te same metody co StringBuilder, ale każda metoda w Stringbufferze jest zsynchronizowany, więc jest bezpieczny dla wątku.
Dane StringBuffer i StringBuilder mogą być tworzone tylko przy użyciu nowego operatora. Są więc przechowywane w pamięci sterty.
-
instancje StringBuilder nie są bezpieczne dla wielu wątków. Jeśli taka synchronizacja jest wymagana, zaleca się użycie StringBuffer.
StringBuffer threadSafe = new StringBuffer("Yash"); threadSafe.append(".M"); threadSafe.toString(); StringBuilder nonSync = new StringBuilder("Yash"); nonSync.append(".M"); nonSync.toString();
-
StringBuffer i StringBuilder mają specjalne metody, takie jak.,
replace(int start, int end, String str)
ireverse()
.Uwaga : StringBuffer i SringBuilder są mutowalne, ponieważ zapewniają implementację
Appendable Interface
.
Kiedy użyć którego.
-
Jeśli a nie zmienisz wartości za każdym razem, lepiej jest użyć
String Class
. Jako część generyków jeśli chcesz posortowaćComparable<T>
lub porównaj wartości, a następnie wybierzString Class
.//ClassCastException: java.lang.StringBuffer cannot be cast to java.lang.Comparable Set<StringBuffer> set = new TreeSet<StringBuffer>(); set.add( threadSafe ); System.out.println("Set : "+ set);
Jeśli zamierzasz modyfikować wartość za każdym razem idź do StringBuilder, który jest szybszy niż StringBuffer. Jeśli wiele wątków modyfikuje wartość, przejdź do StringBuffer.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-24 05:59:36
Również {[0] } jest bezpieczne dla wątków, które StringBuilder
nie są.
Więc w sytuacji w czasie rzeczywistym, gdy różne wątki mają do niego dostęp, StringBuilder
może mieć nieokreślony wynik.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-04 03:32:42
Zauważ, że jeśli używasz Javy 5 lub nowszej, powinieneś użyć StringBuilder
zamiast StringBuffer
. Z dokumentacji API:
Od wydania JDK 5, klasa ta została uzupełniona o równoważną klasę przeznaczoną do użytku przez pojedynczy wątek,
StringBuilder
. KlasaStringBuilder
powinna być zazwyczaj używana zamiast tej, ponieważ obsługuje wszystkie te same operacje, ale jest szybsza, ponieważ nie wykonuje żadnej synchronizacji.
W praktyce prawie nigdy nie użyjesz tego z wielu wątki w tym samym czasie, więc synchronizacja StringBuffer
jest prawie zawsze niepotrzebna.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-04 08:11:37
Osobiście uważam, że nie ma żadnego zastosowania w świecie rzeczywistym dla StringBuffer
. Czy kiedykolwiek chciałbym komunikować się między wieloma wątkami, manipulując sekwencją znaków? To wcale nie brzmi użytecznie, ale może jeszcze nie ujrzałem światła:)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-06 09:46:37
Różnica między String a pozostałymi dwoma klasami polega na tym, że String jest niezmienny, a pozostałe dwie są zmiennymi klasami.
Ale dlaczego mamy dwie klasy w tym samym celu?
Powodem jest to, że {[0] } jest bezpieczne, a StringBuilder
nie jest.
StringBuilder
jest nową klasą na StringBuffer Api
i została wprowadzona w JDK5
i jest zawsze zalecana, jeśli pracujesz w środowisku z pojedynczym wątkiem, ponieważ jest dużo Faster
Szczegółowe informacje można przeczytać http://www.codingeek.com/java/stringbuilder-and-stringbuffer-a-way-to-create-mutable-strings-in-java/
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-05 02:45:14
W Javie, String jest niezmienny. Będąc niezmiennym mamy na myśli, że po utworzeniu ciągu znaków nie możemy zmienić jego wartości. StringBuffer jest zmienny. Po utworzeniu obiektu StringBuffer, po prostu dodajemy zawartość do wartości obiektu zamiast tworzyć nowy obiekt. StringBuilder jest podobny do StringBuffer, ale nie jest bezpieczny dla wątków. Metody Stingbuildera nie są zsynchronizowane, ale w porównaniu do innych ciągów, Stringbuilder działa najszybciej. Możesz się nauczyć różnica pomiędzy String, StringBuilder i StringBuffer poprzez ich implementację.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-11 20:45:26