Jaka jest różnica między String i StringBuffer w Javie?
Jaka jest różnica między String i StringBuffer w Javie?
Czy istnieje maksymalny rozmiar Sznurka?
15 answers
String
służy do manipulowania ciągami znaków, których nie można zmienić(tylko do odczytu i niezmienne).
StringBuffer
służy do reprezentowania znaków, które można modyfikować.
Pod względem wydajności, StringBuffer
jest szybszy podczas wykonywania konkatenacji. Dzieje się tak dlatego, że kiedy połączysz String
, tworzysz nowy obiekt (wewnętrznie) za każdym razem, gdy String
jest niezmienny.
Można również użyć StringBuilder
, który jest podobny do StringBuffer
, z tym że nie jest zsynchronizowany. Maksymalny rozmiar dla z nich to Integer.MAX_VALUE
(231 - 1 = 2,147,483,647) lub maksymalny rozmiar sterty podzielony przez 2 (Zobacz ile znaków może mieć Łańcuch Java?).
Więcej informacji 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
2017-05-23 11:47:25
A String
jest niezmienny, tzn. kiedy jest tworzony, nigdy nie może się zmienić.
A StringBuffer
(lub jego niezsynchronizowany kuzyn StringBuilder
) jest używany, gdy trzeba skonstruować ciąg kawałek po kawałku bez wydajności konstruowania wielu małych String
po drodze.
Maksymalna długość dla obu jest liczbą całkowitą.MAX_VALUE, ponieważ są przechowywane wewnętrznie jako tablice, a tablice Java mają tylko int
dla pseudo-pola długości.
Poprawa wydajności pomiędzy String
s I StringBuffer
S dla wielokrotnej konkatenacji jest dość znacząca. Jeśli uruchomisz poniższy kod testowy, zobaczysz różnicę. Na moim laptopie z Javą 6 dostaję takie wyniki:
Concat with String took: 1781ms Concat with StringBuffer took: 0ms
public class Concat
{
public static String concatWithString()
{
String t = "Cat";
for (int i=0; i<10000; i++)
{
t = t + "Dog";
}
return t;
}
public static String concatWithStringBuffer()
{
StringBuffer sb = new StringBuffer("Cat");
for (int i=0; i<10000; i++)
{
sb.append("Dog");
}
return sb.toString();
}
public static void main(String[] args)
{
long start = System.currentTimeMillis();
concatWithString();
System.out.println("Concat with String took: " + (System.currentTimeMillis() - start) + "ms");
start = System.currentTimeMillis();
concatWithStringBuffer();
System.out.println("Concat with StringBuffer took: " + (System.currentTimeMillis() - start) + "ms");
}
}
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-03-13 17:34:28
String StringBuffer
Immutable Mutable
String s=new String("karthik"); StringBuffer sb=new StringBuffer("karthik")
s.concat("reddy"); sb.append("reddy");
System.out.println(s); System.out.println(sb);
O/P:karthik O/P:karthikreddy
--->once we created a String object ---->once we created a StringBuffer object
we can't perform any changes in the existing we can perform any changes in the existing
object.If we are trying to perform any object.It is nothing but mutablity of
changes with those changes a new object of a StrongBuffer object
will be created.It is nothing but Immutability
of a String object
Use String--->If you require immutabilty
Use StringBuffer---->If you require mutable + threadsafety
Use StringBuilder--->If you require mutable + with out threadsafety
String s=new String("karthik");
--->here 2 objects will be created one is heap and the other is in stringconstantpool(scp) and s is always pointing to heap object
String s="karthik";
--->In this case only one object will be created in scp and s is always pointing to that object only
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-22 06:54:16
String jest klasą niezmienną. Oznacza to, że po utworzeniu instancji instancji ciągu znaków w ten sposób:
String str1 = "hello";
Obiekt w pamięci nie może zostać zmieniony. Zamiast tego będziesz musiał utworzyć nową instancję, skopiować Stary ciąg znaków i dołączyć cokolwiek innego, jak w tym przykładzie:
String str1 = "hello";
str1 = str1 + " world!";
Tak naprawdę dzieje się to, że nie aktualizujemy istniejącego obiektu str1... razem przenosimy nową pamięć, kopiujemy dane "hello" i dodajemy " world!"do końca, wtedy ustawia odniesienie str1, aby wskazywało na tę nową pamięć. Więc to naprawdę wygląda bardziej tak pod maską:
String str1 = "hello";
String str2 = str1 + " world!";
str1 = str2;
Wynika z tego, że ten proces "Kopiuj + Wklej i przenoś rzeczy w pamięci" może być bardzo kosztowny, jeśli jest wykonywany powtarzalnie, szczególnie rekurencyjnie.
Kiedy jesteś w sytuacji konieczności robienia rzeczy w kółko, użyj StringBuilder. Jest zmienna i może dodawać ciągi do końca bieżącego, ponieważ jest z powrotem przez [rosnącą tablicę] (Nie 100%, jeśli jest rzeczywista struktura danych, może być lista).
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-03-04 17:48:41
From the API:
Bezpieczna dla wątku, zmienna sekwencja znaków. Bufor łańcuchów jest podobny do łańcucha, ale można go modyfikować. W dowolnym momencie zawiera określoną sekwencję znaków, ale długość i zawartość sekwencji mogą być zmieniane przez pewne wywołania metod.
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-03-04 16:50:25
StringBuffer jest używany do tworzenia pojedynczego ciągu znaków z wielu łańcuchów, np. gdy chcesz dodać części łańcucha w pętli.
Powinieneś używać Stringbuildera zamiast Stringbuffera, gdy masz tylko jeden wątek, który ma dostęp do Stringbuffera, ponieważ StringBuilder nie jest zsynchronizowany, a tym samym szybszy.
AFAIK w Javie jako języku nie ma górnego limitu dla rozmiaru napisów, ale JVMs prawdopodobnie ma górny limit.
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-03-13 17:27:03
Znalazłem interesującą odpowiedź dla porównania Performance String vs StringBuffer Reggie Hutcherso Źródło: http://www.javaworld.com/javaworld/jw-03-2000/jw-0324-javaperf.html
Java dostarcza klasy StringBuffer i String, A Klasa String jest używana do manipulowania ciągami znaków, których nie można zmienić. Mówiąc najprościej, obiekty typu String są tylko do odczytu i niezmienne. Klasa StringBuffer służy do reprezentowania znaków, które mogą być zmodyfikowany.
Znacząca różnica wydajności między tymi dwoma klasami polega na tym, że StringBuffer jest szybszy niż String podczas wykonywania prostych konkatenacji. W kodzie manipulacji ciągami znaków ciągi znaków są rutynowo łączone. Używając klasy String, konkatenacje są zazwyczaj wykonywane w następujący sposób:
String str = new String ("Stanford ");
str += "Lost!!";
Jeśli chcesz użyć StringBuffer do wykonania tej samej konkatenacji, potrzebujesz kodu, który wygląda tak:
StringBuffer str = new StringBuffer ("Stanford ");
str.append("Lost!!");
Deweloperzy zazwyczaj zakładają, że pierwszy przykład powyżej jest bardziej wydajny, ponieważ uważają, że drugi przykład, który używa metody append do łączenia, jest bardziej kosztowny niż pierwszy przykład, który używa operatora + do łączenia dwóch obiektów łańcuchowych.
Operator + wydaje się niewinny, ale wygenerowany kod powoduje pewne niespodzianki. Używanie Stringbuffera do konkatenacji może w rzeczywistości wygenerować kod, który jest znacznie szybszy niż użycie ciągu znaków. Aby dowiedzieć się, dlaczego tak jest, musimy zbadać wygenerowany kod bajtowy z naszych dwóch przykładów. Kod bajtowy przykładu używającego ciągu znaków wygląda następująco:
0 new #7 <Class java.lang.String>
3 dup
4 ldc #2 <String "Stanford ">
6 invokespecial #12 <Method java.lang.String(java.lang.String)>
9 astore_1
10 new #8 <Class java.lang.StringBuffer>
13 dup
14 aload_1
15 invokestatic #23 <Method java.lang.String valueOf(java.lang.Object)>
18 invokespecial #13 <Method java.lang.StringBuffer(java.lang.String)>
21 ldc #1 <String "Lost!!">
23 invokevirtual #15 <Method java.lang.StringBuffer append(java.lang.String)>
26 invokevirtual #22 <Method java.lang.String toString()>
29 astore_1
Bajt w miejscach od 0 do 9 jest wykonywany dla pierwszej linii kodu, a mianowicie:
String str = new String("Stanford ");
Wtedy bajt w miejscach od 10 do 29 jest wykonywany dla konkatenacji:
str += "Lost!!";
Robi się tu ciekawie. Kod bajtowy wygenerowany dla połączenia tworzy obiekt StringBuffer, a następnie wywołuje jego metodę append: tymczasowy obiekt StringBuffer jest utworzony w lokalizacji 10, a jego metoda append jest wywoływana w lokalizacji 23. Ponieważ Klasa String jest niezmienna, do konkatenacji musi być użyty StringBuffer.
Po wykonaniu konkatenacji na obiekcie StringBuffer, musi on zostać z powrotem przekonwertowany na łańcuch znaków. Odbywa się to za pomocą wywołania metody toString w lokalizacji 26. Metoda ta wytworzy nowy obiekt String z tymczasowego obiektu StringBuffer. Tworzenie tego tymczasowego obiektu StringBuffer i jego późniejsze konwersja z powrotem do obiektu String jest bardzo kosztowna.
Podsumowując, dwie linijki powyższego kodu skutkują powstaniem trzech obiektów:
- obiekt typu String w miejscu 0
- obiekt StringBuffer w miejscu 10
- obiekt typu String w miejscu 26
Spójrzmy teraz na kod bajtowy wygenerowany dla przykładu przy użyciu StringBuffer:
0 new #8 <Class java.lang.StringBuffer>
3 dup
4 ldc #2 <String "Stanford ">
6 invokespecial #13 <Method java.lang.StringBuffer(java.lang.String)>
9 astore_1
10 aload_1
11 ldc #1 <String "Lost!!">
13 invokevirtual #15 <Method java.lang.StringBuffer append(java.lang.String)>
16 pop
Bajtowy kod w miejscach od 0 do 9 jest wykonywany dla pierwszej linii kod:
StringBuffer str = new StringBuffer("Stanford ");
Kod bajtowy w miejscach od 10 do 16 jest następnie wykonywany dla konkatenacji:
str.append("Lost!!");
Zauważ, że tak jak w pierwszym przykładzie, kod ten wywołuje metodę append obiektu StringBuffer. W przeciwieństwie do pierwszego przykładu, nie ma potrzeby tworzenia tymczasowego bufora StringBuffer, a następnie przekształcania go w obiekt String. Ten kod tworzy tylko jeden obiekt, StringBuffer, w lokalizacji 0.
Podsumowując, konkatenacja Stringbuffera jest znacznie szybszy niż konkatenacja strun. Oczywiście, StringBuffers powinny być używane w tego typu operacji, gdy jest to możliwe. Jeśli pożądana jest funkcjonalność klasy String, rozważ użycie Stringbuffera do konkatenacji, a następnie wykonanie jednej konwersji na String.
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-11-23 06:55:49
A StringBuffer
lub jego młodszy i szybszy brat StringBuilder
jest preferowany, gdy masz zamiar zrobić wiele konkatenacji strun w smaku
string += newString;
Lub równoważnie
string = string + newString;
Ponieważ powyższe konstrukty domyślnie tworzą nowy ciąg za każdym razem, który będzie olbrzymią wydajnością i spadkiem. A StringBuffer
/ StringBuilder
jest pod kapturem najlepiej porównać z dynamicznie rozszerzalnym List<Character>
.
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-03-13 17:29:49
A String
jest niezmienną tablicą znaków.
A {[1] } jest zmienną tablicą znaków. Często konwertowane z powrotem do String
po zakończeniu mutacji.
Ponieważ oba są tablicami, maksymalny rozmiar dla obu jest równy maksymalnemu rozmiarowi liczby całkowitej, która wynosi 2^31-1 (zobacz JavaDoc, sprawdź także JavaDoc dla obu String
i StringBuffer
).Jest tak, ponieważ .length
argument tablicy jest prymitywnym int
. (Patrz Tablice ).
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-03-13 17:35:28
String jest niezmienny, co oznacza, że gdy wykonujesz operację na łańcuchu, naprawdę tworzysz cały Nowy Łańcuch.
StringBuffer jest zmienny i można do niego dołączyć, a także zresetować jego długość do 0.
W praktyce kompilator wydaje się używać StringBuffer podczas łączenia łańcuchów ze względów wydajnościowych.
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-03-04 16:50:41
String is immutable.
Dlaczego? Sprawdź TUTAJ .
StringBuffer is not. It is thread safe.
Kolejne pytania, takie jak Kiedy używać które i inne pojęcia można rozgryźć po to .
Mam nadzieję, że to pomoże.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-07-25 06:44:01
Chociaż rozumiem, że nie jest to główny czynnik różnicujący, zauważyłem dzisiaj, że StringBuffer(i StringBuilder) dostarcza ciekawych metod, których String nie ma.
- reverse ()
- setCharAt ()
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-11-20 03:14:56
Poprzez wydrukowanie hashcode obiektu String / StringBuffer po udowodnieniu dowolnej operacji dołączania, obiekt String jest odtwarzany wewnętrznie za każdym razem z nowymi wartościami, zamiast używać tego samego obiektu String.
public class MutableImmutable {
/**
* @param args
*/
public static void main(String[] args) {
System.out.println("String is immutable");
String s = "test";
System.out.println(s+"::"+s.hashCode());
for (int i = 0; i < 10; i++) {
s += "tre";
System.out.println(s+"::"+s.hashCode());
}
System.out.println("String Buffer is mutable");
StringBuffer strBuf = new StringBuffer("test");
System.out.println(strBuf+"::"+strBuf.hashCode());
for (int i = 0; i < 10; i++) {
strBuf.append("tre");
System.out.println(strBuf+"::"+strBuf.hashCode());
}
}
}
Wyjście: Wyświetla wartość obiektu wraz z jego hashcode
String is immutable
test::3556498
testtre::-1422435371
testtretre::-1624680014
testtretretre::-855723339
testtretretretre::2071992018
testtretretretretre::-555654763
testtretretretretretre::-706970638
testtretretretretretretre::1157458037
testtretretretretretretretre::1835043090
testtretretretretretretretretre::1425065813
testtretretretretretretretretretre::-1615970766
String Buffer is mutable
test::28117098
testtre::28117098
testtretre::28117098
testtretretre::28117098
testtretretretre::28117098
testtretretretretre::28117098
testtretretretretretre::28117098
testtretretretretretretre::28117098
testtretretretretretretretre::28117098
testtretretretretretretretretre::28117098
testtretretretretretretretretretre::28117098
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-08-03 17:05:05
Różnice są
- Tylko w klasie String + operator jest przeciążony. Możemy połączyć dwa obiekty łańcuchowe za pomocą + operator, ale w przypadku StringBuffer nie możemy.
-
String Klasa nadpisuje ToString (), equals (), hashCode () klasy obiektu, ale StringBuffer tylko nadpisuje ToString ().
String s1 = new String("abc"); String s2 = new String("abc"); System.out.println(s1.equals(s2)); // output true StringBuffer sb1 = new StringBuffer("abc"); StringBuffer sb2 = new StringBuffer("abc"); System.out.println(sb1.equals(sb2)); // output false
-
String class jest zarówno Serializowalny jak i porównywalne , ale StringBuffer jest tylko Serializowalny .
Set<StringBuffer> set = new TreeSet<StringBuffer>(); set.add(sb1); set.add(sb2); System.out.println(set); // gives ClassCastException because there is no Comparison mechanism
Możemy utworzyć obiekt String z operatorem new i bez niego, ale obiekt StringBuffer można utworzyć tylko przy użyciu operatora new.
- String jest niezmienny, ale StringBuffer jest zmienny.
- StringBuffer jest zsynchronizowany, podczas gdy String nie jest.
- StringBuffer ma wbudowaną metodę reverse () , ale String nie ma jej.
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-01-18 05:06:43
Performance wise StringBuffer jest znacznie lepszy niż String ; ponieważ za każdym razem, gdy zastosujesz konkatenację na obiekcie String, przy każdej konkatenacji tworzony jest nowy obiekt String.
Główna zasada: String są niezmienne (niemodyfikowalne) i StringBuffer są mutowalne(modyfikowalne)
Oto eksperyment programowy, w którym uzyskujesz różnicę wydajności
public class Test {
public static int LOOP_ITERATION= 100000;
public static void stringTest(){
long startTime = System.currentTimeMillis();
String string = "This";
for(int i=0;i<LOOP_ITERATION;i++){
string = string+"Yasir";
}
long endTime = System.currentTimeMillis();
System.out.println(endTime - startTime);
}
public static void stringBufferTest(){
long startTime = System.currentTimeMillis();
StringBuffer stringBuffer = new StringBuffer("This");
for(int i=0;i<LOOP_ITERATION;i++){
stringBuffer.append("Yasir");
}
long endTime = System.currentTimeMillis();
System.out.println(endTime - startTime);
}
public static void main(String []args){
stringTest()
stringBufferTest();
}
}
Wyjście String są w mojej maszynie 14800
Wyjście z StringBuffer są w mojej maszynie 14
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-06-11 10:21:34