Скажите, пожалуйста, в реальном времени сравнить String
, StringBuffer
и StringBuilder
?
String, StringBuffer и StringBuilder
Ответ 1
Разность взаимозаменяемости:
String
неизменный, если вы пытаетесь изменить их значения, создается другой объект, тогда как StringBuffer
и StringBuilder
являются изменчивыми, поэтому они могут изменять их значения.
Разница потоков:
Разница между StringBuffer
и StringBuilder
заключается в том, что StringBuffer
является потокобезопасным. Поэтому, когда приложение нужно запускать только в одном потоке, лучше использовать StringBuilder
. StringBuilder
более эффективен, чем StringBuffer
.
Ситуации:
- Если ваша строка не изменится, используйте класс String, потому что объект
String
является неизменным. - Если ваша строка может измениться (например: много логики и операций в построении строки) и будет доступен только из одного потока, использование
StringBuilder
будет достаточно хорошим. - Если ваша строка может измениться и будет доступна из нескольких потоков, используйте
StringBuffer
, потому чтоStringBuffer
является синхронным, поэтому вы обеспечиваете безопасность потоков.
Ответ 2
- Вы используете
String
, когда необходима неизменяемая структура; получение новой последовательности символов изString
может приводить к неприемлемому снижению производительности либо в процессорном времени, либо в памяти (получение подстрок является эффективным ЦП, поскольку данные не копируются, но это означает, что потенциально гораздо больший объем данных может оставаться выделенным). - Вы используете
StringBuilder
, когда вам нужно создать изменяемую последовательность символов, как правило, чтобы объединить несколько последовательностей символов вместе. - Вы используете
StringBuffer
в тех же обстоятельствах, что использовали быStringBuilder
, но когда изменения в базовой строке должны быть синхронизированы (потому что несколько потоков читают/изменяют строковый буфер).
См. пример здесь.
Ответ 3
Основы:
String
является неизменным классом, его нельзя изменить.
StringBuilder
- это изменяемый класс, который может быть добавлен, заменены или удалены символы и в конечном итоге преобразованы в String
StringBuffer
- это исходная синхронизированная версия StringBuilder
Вы должны предпочесть StringBuilder
во всех случаях, когда у вас есть только один поток, обращающийся к вашему объекту.
Детали:
Также обратите внимание, что StringBuilder/Buffers
не являются волшебными, они просто используют Array в качестве объекта поддержки и что Array необходимо перераспределить, когда он заполняется. Будьте уверены, и создайте свои объекты StringBuilder/Buffer
достаточно крупными изначально, где им не нужно постоянно изменять размер каждый раз, когда вызывается .append()
.
Повторная калибровка может стать очень вырожденной. Он в основном изменяет размер массива поддержки в 2 раза по сравнению с его текущим размером каждый раз, когда его нужно расширить. Это может привести к тому, что большие объемы ОЗУ будут выделены и не будут использоваться, когда классы StringBuilder/Buffer
начнут расти.
В Java String x = "A" + "B";
используется StringBuilder
за кулисами. Таким образом, для простых случаев нет никакой пользы от объявления вашего. Но если вы строите большие объекты String
, скажем, менее 4k, то объявление StringBuilder sb = StringBuilder(4096);
намного эффективнее, чем конкатенация, или используя конструктор default, который составляет всего 16 символов. Если ваш String
будет меньше 10k, тогда инициализируйте его с конструктором до 10k, чтобы быть в безопасности. Но если он инициализируется до 10k, тогда вы пишете 1 символ более 10 тыс., Он будет перераспределен и скопирован в массив 20 тыс. Поэтому инициализация максимума лучше, чем низкая.
В случае автоматического повторного размера, на 17-м символе, массив архивации перераспределяется и копируется до 32 символов, а на 33-м символе это происходит снова, и вы получаете перераспределение и копирование массива на 64 символа. Вы можете увидеть, как это вырождается до лотов перераспределений и копий, которые вы действительно пытаетесь избежать использования StringBuilder/Buffer
в первую очередь.
Это из исходного кода JDK 6 для 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);
}
Лучшей практикой является инициализация StringBuilder/Buffer
немного больше, чем вы думаете, что вам нужно, если вы не знаете сразу, насколько велика String
, но вы можете догадаться. Одно распределение немного больше памяти, чем вам нужно, будет лучше, чем много перераспределений и копий.
Также будьте осторожны с инициализацией StringBuilder/Buffer
с String
, поскольку для этого будет выделен только размер String + 16 символов, который в большинстве случаев просто запустит процесс вырожденного повторного выделения и копирования, который вы пытаетесь избежать. Ниже приведен исходный код Java.
public StringBuilder(String str) {
super(str.length() + 16);
append(str);
}
Если вы случайно закончите с экземпляром StringBuilder/Buffer
, который вы не создали и не можете управлять вызываемым конструктором, существует способ избежать вырожденного перераспределения и копирования. Вызовите .ensureCapacity()
с размером, который вы хотите, чтобы ваш итоговый String
вписывался в.
Альтернативы:
Как примечание, если вы делаете действительно тяжелое String
создание и манипулирование, существует гораздо более ориентированная на производительность альтернатива, называемая Ropes.
Другой альтернативой является создание реализации StringList
путем подклассификации ArrayList<String>
и добавление счетчиков для отслеживания количества символов для каждой операции .append()
и других мутаций в списке, а затем переопределить .toString()
на создайте StringBuilder
точного размера, который вам нужен, и прокрутите список и создайте вывод, вы даже можете сделать эту переменную StringBuilder
переменной экземпляра и "кешем" результаты .toString()
и только ее нужно повторно сгенерировать когда что-то меняется.
Также не забывайте о String.format()
при создании файла с фиксированным форматированием, который может быть оптимизирован компилятором по мере их улучшения.
Ответ 4
Вы имеете в виду, для конкатенации?
Пример реального мира: вы хотите создать новую строку из многих других.
Например, чтобы отправить сообщение:
Строка
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()
Или
String s = new StringBuilder(100).appe..... etc. ...
// The difference is a size of 100 will be allocated upfront as fuzzy lollipop points out.
StringBuffer (синтаксис точно такой же, как у StringBuilder, эффекты отличаются)
О
StringBuffer
vs. StringBuilder
Первая синхронизирована, а позже - нет.
Итак, если вы вызываете его несколько раз в одном потоке (что составляет 90% случаев), StringBuilder
будет быстрее намного, потому что он не перестанет видеть, владеет ли он блокировка резьбы.
Таким образом, рекомендуется использовать StringBuilder
(если, конечно, у вас есть несколько потоков, обращающихся к нему в одно и то же время, что редко)
String
(с помощью оператора +) может быть оптимизирована компилятором для использования под StringBuilder
снизу, поэтому больше не о чем беспокоиться, в старшие дни Java это было то, что каждый говорит, что можно избежать любой ценой, потому что каждая конкатенация создала новый объект String. Современные компиляторы больше этого не делают, но по-прежнему рекомендуется использовать StringBuilder
вместо этого, если вы используете "старый" компилятор.
изменить
Просто для кого это любопытно, это то, что делает компилятор для этого класса:
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
}
Строки с номером 5-27 предназначены для строки с именем "literal"
Строки с номером 31-53 предназначены для строки с именем "строитель"
Нет никакой разницы, именно тот же тот же код выполняется для обеих строк.
Ответ 5
Кроме того, StringBuffer
является потокобезопасным, а StringBuilder
- нет.
Поэтому в ситуации реального времени, когда к нему обращаются разные потоки, StringBuilder
может иметь неопределенный результат.
Ответ 6
Обратите внимание, что если вы используете Java 5 или новее, вы должны использовать StringBuilder
вместо StringBuffer
. Из документации API:
С момента выпуска JDK 5 этот класс был дополнен эквивалентным классом, предназначенным для использования одним потоком,
StringBuilder
. КлассStringBuilder
обычно должен использоваться в предпочтении этому, поскольку он поддерживает все те же операции, но быстрее, поскольку он не выполняет синхронизацию.
На практике вы почти никогда не будете использовать это из нескольких потоков одновременно, поэтому синхронизация, выполняемая StringBuffer
, почти всегда является ненужной служебной информацией.
Ответ 7
Разница между String и другими двумя классами заключается в том, что String неизменяема, а две другие являются изменяемыми классами.
Но почему у нас есть два класса для одной цели?
Причина в том, что StringBuffer
является потокобезопасным, а StringBuilder
- нет.
StringBuilder
- новый класс на StringBuffer Api
, и он был введен в JDK5
и всегда рекомендуется, если вы работаете в среде с одним потоком, так как это значительно Faster
Для получения подробной информации вы можете прочитать http://www.codingeek.com/java/stringbuilder-and-stringbuffer-a-way-to-create-mutable-strings-in-java/
Ответ 8
---------------------------------------------------------------------------------- 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 ----------------------------------------------------------------------------------
Ответ 9
Лично я не думаю, что для StringBuffer
существует реальное использование в мире. Когда я когда-нибудь захочу общаться между несколькими потоками, манипулируя символьной последовательностью? Это совсем не полезно, но, возможно, мне еще нужно увидеть свет:)
Ответ 10
В java Строка является неизменной. Будучи неизменными, мы подразумеваем, что после создания String мы не можем изменить его значение. StringBuffer изменен. Когда объект StringBuffer создается, мы просто добавляем контент к значению объекта вместо создания нового объекта. StringBuilder похож на StringBuffer, но он не является потокобезопасным. Методы StingBuilder не синхронизированы, но по сравнению с другими строками, Stringbuilder работает быстрее всего. Вы можете узнать разницу между String, StringBuilder и StringBuffer путем их реализации.
Ответ 11
Строка
String class
представляет символьные строки. Все строковые литералы в программе Java, такие как "abc"
, реализуются как экземпляры этого класса.
Строковые объекты неизменяемы после их создания мы не можем изменить. (Строки являются константами)
-
Если String создается с использованием конструктора или метода, эти строки будут храниться в Память кучи, а также
SringConstantPool
. Но перед сохранением в пуле он вызывает методintern()
для проверки доступности объекта с тем же содержимым в пуле с использованием метода equals. Если String-copy доступен в пуле, то возвращается ссылка. В противном случае объект String добавляется в пул и возвращает ссылку.- Язык Java обеспечивает специальную поддержку оператора конкатенации строк (
+
) и для преобразования других объектов в строки. Конкатенация строк реализуется через класс StringBuilder (или StringBuffer) и его метод добавления.
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); }
- Язык Java обеспечивает специальную поддержку оператора конкатенации строк (
-
Строковые литералы хранятся в
StringConstantPool
.String onlyPool = "Yash";
StringBuilder и StringBuffer являются изменяемой последовательностью символов. Это означает, что можно изменить значение этих объектов. StringBuffer имеет те же методы, что и StringBuilder, но каждый метод в StringBuffer синхронизирован, поэтому он является потокобезопасным.
-
Данные StringBuffer и StringBuilder могут создаваться только с использованием нового оператора. Таким образом, они сохраняются в памяти кучи.
-
Экземпляры StringBuilder небезопасны для использования несколькими потоками. Если такая синхронизация требуется, рекомендуется использовать StringBuffer.
StringBuffer threadSafe = new StringBuffer("Yash"); threadSafe.append(".M"); threadSafe.toString(); StringBuilder nonSync = new StringBuilder("Yash"); nonSync.append(".M"); nonSync.toString();
-
У StringBuffer и StringBuilder есть специальные методы вроде.,
replace(int start, int end, String str)
иreverse()
.ПРИМЕЧАНИЕ: StringBuffer и SringBuilder являются изменяемыми, поскольку они обеспечивают реализацию
Appendable Interface
.
Когда использовать какой.
-
Если вы не собираетесь менять значение каждый раз, тогда лучше использовать
String class
. Как часть Generics, если вы хотите СортировкаComparable<T>
или сравните значения, перейдите кString 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);
-
Если вы собираетесь изменять значение каждый раз, когда идет StringBuilder, который быстрее, чем StringBuffer. Если несколько потоков изменяют значение, перейдите для StringBuffer.