В чем основное различие между StringBuffer и StringBuilder?
Есть ли проблемы с производительностью при выборе любого из них?




StringBuffer синхронизирован, StringBuilder нет.
и синхронизация практически не требуется. Если кто-то хочет синхронизировать StringBuilder, он может просто окружить весь блок кода синхронизированным (sb) {} на экземпляре.
@locka Я бы сказал, что StringBuffer никогда не бывает хорошей идеей (если у вас нет API, который этого требует) vanillajava.blogspot.de/2013/04/…
Единственное место, где я вижу StringBuffer, - это консольный вывод и различные утилиты для ведения журнала: многие потоки могут выводить конфликт. Поскольку вы не хотите, чтобы 2 вывода смешивались ... но обычно синхронизация на уровне StringBuffer слишком низка, вы захотите синхронизировать в приложении, таком как levelm, поэтому ответ locka является лучшим, а StringBuffer должен быть устаревшим. Это сэкономит время на проверку кода новичкам.
Хорошая мнемоника для тех, кто смешивает эти два - BuFFer был первой, более старой и, следовательно, синхронизированной реализацией. Новый класс Builder использует шаблон Builder и является асинхронным.
Но StringBuffer медленнее, чем StringBuilder. Вы выбираете тот, который вам больше нравится, в зависимости от того, над какими приложениями вы работаете.
Другое отличие состоит в том, что StringBuffer можно использовать с Matcher#appendReplacement, тогда как StringBuilderне могу. Это очень неприятная разница в API, особенно потому, что Matcher не является потокобезопасным, поэтому для appendReplacement нет необходимости требовать синхронизации.
Чтобы найти более подробную информацию о том, какова фактическая причина сбоя StringBuilder в многопоточной среде, я задал вопрос, который может быть полезным stackoverflow.com/questions/31375718/…
Почему в последней редакции говорится, что StringBuilder является неизменяемым объектом? Он не является неизменным и не является объектом, это класс. Это не должно быть частью основного ответа.
@ D.Everhard Согласился, вообще-то я тоже запутался. Это нужно исправить.
@sblundy StringBuilder не является неизменным, шокирован, поскольку никто не указал
StringBuffer выполняется быстрее, чем StringBuilder.
В основном методы StringBuffer синхронизируются, а StringBuilder - нет.
Операции «почти» одинаковы, но использование синхронизированных методов в одном потоке излишне.
Это в значительной степени об этом.
Цитата из StringBuilder API:
This class [StringBuilder] provides an API compatible with StringBuffer, but with no guarantee of synchronization. This class is designed for use as a drop-in replacement for StringBuffer in places where the string buffer was being used by a single thread (as is generally the case). Where possible, it is recommended that this class be used in preference to StringBuffer as it will be faster under most implementations.
Итак, это было сделано, чтобы заменить его.
То же самое произошло с Vector и ArrayList.
Также с Hashtable и HashMap.
StringBuilder был представлен в Java 1.5, поэтому он не будет работать с более ранними JVM.
Из Javadocs:
StringBuilder class provides an API compatible with StringBuffer, but with no guarantee of synchronization. This class is designed for use as a drop-in replacement for StringBuffer in places where the string buffer was being used by a single thread (as is generally the case). Where possible, it is recommended that this class be used in preference to StringBuffer as it will be faster under most implementations.
Срок службы версии 1.4 подошел к концу, так что вряд ли стоит беспокоиться о версиях до 1.5.
@ tomHawtin-tackline не обязательно - есть корпоративные продукты до 1.4, которые большинство из нас использует ежедневно. Также BlackBerry java основана на 1.4, и она все еще очень актуальна.
И CDC, и CLDC не имеют StringBuilder.
StringBuilder не является потокобезопасным. Строковый буфер есть. Подробнее здесь.
Обновлено: Что касается производительности, после того, как горячая точка срабатывает, StringBuilder становится победителем. Однако для небольших итераций разница в производительности незначительна.
StringBuffer
StringBuilder
StringBuffer без каких-либо других измененийПРИМЕЧАНИЕ. Только одиночные операции являются потокобезопасными, а множественные - нет. например, если вы дважды звоните append или append и toString небезопасны.
StringBuffer используется для хранения символьных строк, которые будут изменены (объекты String не могут быть изменены). Он автоматически расширяется по мере необходимости. Связанные классы: String, CharSequence.
StringBuilder был добавлен в Java 5. Он во всех отношениях идентичен StringBuffer, за исключением того, что он не синхронизирован, что означает, что если несколько потоков обращаются к нему одновременно, могут возникнуть проблемы. Для однопоточных программ, наиболее распространенный случай, когда исключение накладных расходов на синхронизацию делает StringBuilder немного быстрее.
Однопоточные программы - не самый распространенный случай в Java, но StringBuilder обычно являются локальными для метода, где они видны только одному потоку.
StringBuffer синхронизирован, а StringBuilder - нет. В результате StringBuilder быстрее, чем StringBuffer.
StringBuilder быстрее, чем StringBuffer, потому что это не synchronized.
Вот простой тест производительности:
public class Main {
public static void main(String[] args) {
int N = 77777777;
long t;
{
StringBuffer sb = new StringBuffer();
t = System.currentTimeMillis();
for (int i = N; i --> 0 ;) {
sb.append("");
}
System.out.println(System.currentTimeMillis() - t);
}
{
StringBuilder sb = new StringBuilder();
t = System.currentTimeMillis();
for (int i = N; i > 0 ; i--) {
sb.append("");
}
System.out.println(System.currentTimeMillis() - t);
}
}
}
тестовый забег дает номера 2241 ms для StringBuffer по сравнению с 753 ms для StringBuilder.
Я изменил строковый литерал на что-то большее: «быстрая коричневая лиса» и получил более интересные результаты. В основном они примерно такие же быстрые. На самом деле у меня закончилась память, поэтому пришлось удалить несколько семерок. Объяснение: синхронизация оптимизирована от точки доступа. По сути, вы просто измеряете время, необходимое точке доступа для этого (и, возможно, еще несколько оптимизаций).
Согласитесь с Альфредо. Добавление к комментарию Jiles, когда используется с одной строкой символов ("A"), соотношение будет как 2 x 1 (2 для StringBuffer). используя более 3 символов, и я получил "OutOfMemoryError"! (-Xms512m / -Xmx1024m)
Перед тем как разогреться. Этот тест несправедлив к StringBuffer. Кроме того, было бы хорошо, если бы он действительно что-то добавлял. Фактически, я перевернул тест, добавил случайную строку и получил противоположный тест. Можно сказать, что простым тестам доверять нельзя. Напротив, StringBuffer работает быстрее. 5164 для StringBuilder и 3699 для StringBuffer hastebin.com/piwicifami.avrasm
Если кто-то пытается запускать тесты снова и снова, в разном порядке, разница едва заметна, и, откровенно говоря, не ясно, кто победит.
Это первый раз, когда я вижу --> 0 в петле. Мне потребовалось время, чтобы понять, что это значит. Это то, что действительно используется на практике вместо обычного синтаксиса ...; i > 0; i--?
Да, даже я не использовал такое для конструкций -> 0, я пробовал использовать {for (int i = 0; i --> N ;)}, который не работал? .
Этот i --> действительно раздражает с точки зрения синтаксиса ... Сначала я подумал, что это стрелка из-за комментариев об искусстве ASCII.
@ D.Everhard и другие: Этот может быть для вас интересным чтением.
Другие заключают с другими результатами: alblue.bandlem.com/2016/04/jmh-stringbuffer-stringbuilder.ht мл. Тесты действительно должны выполняться с JMH, а не с простым main(). Кроме того, ваш тест несправедлив. Нет никакой разминки.
какой был бы прекрасный мир, если бы for (int i = N; i --> 0 ;) засчитали как трюк для вечеринки
Этот тест неточен, когда код находится внутри первой лупы, JVM необходимо загружать массивы изнутри, поскольку они используются внутри самого конструктора строк, но он не делает этого в тесте de stringbuilder, поскольку он уже загрузил его.
String - это неизменяемый объект, что означает, что значение не может быть изменено, тогда как StringBuffer является изменяемым.
StringBuffer синхронизирован, следовательно, потокобезопасен, тогда как StringBuilder нет и подходит только для однопоточных экземпляров.
просто потому, что StringBuffer имеет синхронизированный код, не обязательно означает, что StringBuffer является потокобезопасным. Рассмотрим следующий пример: StringBuffer testingBuffer = "stackoverflow"; Теперь Thread-1 пытается добавить «1» к testBuffer, а Thread-2 пытается добавить «2» к testingBuffer. Теперь, несмотря на то, что метод append () синхронизирован, вы не можете быть уверены, будет ли значение testingBuffer «stackoverflow12» или «stackoverflow21». На самом деле Oracle рекомендует использовать построитель строк вместо буфера строк. Надеюсь, это помогло :)
StringBuilder и StringBuffer почти одинаковы. Разница в том, что StringBuffer синхронизирован, а StringBuilder - нет. Хотя StringBuilder быстрее, чем StringBuffer, разница в производительности очень небольшая. StringBuilder - это замена StringBuffer SUN. Он просто избегает синхронизации со всеми общедоступными методами. Скорее, их функциональность такая же.
Пример правильного использования:
Если ваш текст будет изменяться и используется несколькими потоками, то лучше использовать StringBuffer. Если ваш текст будет изменяться, но используется одним потоком, используйте StringBuilder.
Лучше использовать StringBuilder, так как он не синхронизированный и, следовательно, обеспечивает лучшую производительность. StringBuilder - это безотказная замена более старого StringBuffer.
Если, конечно, ваше приложение не является многопоточным. :)
@Mark true, но в большинстве случаев StringBu(ff|ild)er - это локальная переменная, используемая только одним потоком.
@MarkMcKenna: даже в многопоточном приложении часто приходилось либо использовать внешнюю блокировку, либо делать дополнительную работу, чтобы ее избежать. Например, если два потока хотят добавить запись, содержащую несколько строк, в построитель строк, им придется агрегировать данные, которые нужно добавить, а затем добавить их как единое целое, даже если это было бы быстрее - при отсутствии проблем с потоками - просто выполнить последовательность дискретных операций добавления.
javadoc объясняет разницу:
This class provides an API compatible with StringBuffer, but with no guarantee of synchronization. This class is designed for use as a drop-in replacement for StringBuffer in places where the string buffer was being used by a single thread (as is generally the case). Where possible, it is recommended that this class be used in preference to StringBuffer as it will be faster under most implementations.
StringBuilder (представленный в Java 5) идентичен StringBuffer, за исключением того, что его методы не синхронизируются. Это означает, что он имеет лучшую производительность, чем последний, но недостатком является то, что он не является потокобезопасным.
Подробнее читайте в руководство.
But needed to get the clear difference with the help of an example?
StringBuffer or StringBuilder
Просто используйте StringBuilder, если вы действительно не пытаетесь разделить буфер между потоками. StringBuilder - это несинхронизированный (меньше накладных расходов = более эффективный) младший брат исходного синхронизированного класса StringBuffer.
StringBuffer был первым. Sun заботилась о корректности при любых условиях, поэтому на всякий случай сделали его синхронизированным, чтобы сделать его потокобезопасным.
StringBuilder появился позже. В большинстве случаев использование StringBuffer было однопоточным и не требовало затрат на синхронизацию.
Поскольку StringBuilder является безотказная замена для StringBuffer без синхронизации, не будет различий между любыми примерами.
Если вы находятся пытаетесь разделить между потоками, вы можете использовать StringBuffer, но подумайте, нужна ли синхронизация более высокого уровня, например возможно, вместо использования StringBuffer вы должны синхронизировать методы, использующие StringBuilder.
Первый хороший ответ !! Дело в том, что «если вы не разделяете буфер между потоками»
В одиночных потоках - StringBuffer ненамного медленнее StringBuilder, благодаря оптимизации JVM. А в многопоточности нельзя безопасно использовать StringBuilder.
Вот мой тест (не тест, а просто тест):
public static void main(String[] args) {
String withString = "";
long t0 = System.currentTimeMillis();
for (int i = 0 ; i < 100000; i++){
withString+ = "some string";
}
System.out.println("strings:" + (System.currentTimeMillis() - t0));
t0 = System.currentTimeMillis();
StringBuffer buf = new StringBuffer();
for (int i = 0 ; i < 100000; i++){
buf.append("some string");
}
System.out.println("Buffers : "+(System.currentTimeMillis() - t0));
t0 = System.currentTimeMillis();
StringBuilder building = new StringBuilder();
for (int i = 0 ; i < 100000; i++){
building.append("some string");
}
System.out.println("Builder : "+(System.currentTimeMillis() - t0));
}
Результатов:
струны: 319740
Буферы: 23
Строитель: 7!
Таким образом, построители быстрее, чем буферы, и НАМНОГО быстрее, чем конкатенация строк. Теперь давайте используем Исполнитель для нескольких потоков:
public class StringsPerf {
public static void main(String[] args) {
ThreadPoolExecutor executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
//With Buffer
StringBuffer buffer = new StringBuffer();
for (int i = 0 ; i < 10; i++){
executorService.execute(new AppendableRunnable(buffer));
}
shutdownAndAwaitTermination(executorService);
System.out.println(" Thread Buffer : "+ AppendableRunnable.time);
//With Builder
AppendableRunnable.time = 0;
executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
StringBuilder builder = new StringBuilder();
for (int i = 0 ; i < 10; i++){
executorService.execute(new AppendableRunnable(builder));
}
shutdownAndAwaitTermination(executorService);
System.out.println(" Thread Builder: "+ AppendableRunnable.time);
}
static void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // code reduced from Official Javadoc for Executors
try {
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow();
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (Exception e) {}
}
}
class AppendableRunnable<T extends Appendable> implements Runnable {
static long time = 0;
T appendable;
public AppendableRunnable(T appendable){
this.appendable = appendable;
}
@Override
public void run(){
long t0 = System.currentTimeMillis();
for (int j = 0 ; j < 10000 ; j++){
try {
appendable.append("some string");
} catch (IOException e) {}
}
time+=(System.currentTimeMillis() - t0);
}
}
Теперь StringBuffers принимает 157 мс для 100000 добавлений. Это не тот же тест, но по сравнению с предыдущими 37 мс, можно смело предположить, что Добавление StringBuffers медленнее при использовании многопоточности. Причина в том, что JIT / hotspot / compiler / something выполняет оптимизацию, когда обнаруживает, что для проверки блокировок требуется нет.
Но с StringBuilder у вас есть java.lang.ArrayIndexOutOfBoundsException, потому что параллельный поток пытается добавить что-то там, где он не должен.
Вывод состоит в том, что вам не нужно гнаться за StringBuffers. А если у вас есть потоки, подумайте о том, что они делают, прежде чем пытаться выиграть несколько наносекунд.
Вы забыли сделать "t0 = System.currentTimeMillis ();" перед выполнением теста StringBuilder. Таким образом, рисунок, отображаемый для StringBuilder, на самом деле является временем, которое потребовалось для запуска теста строкового буфера И конструктора строк. Добавьте эту строку, и вы увидите, что StringBuilder БЫСТРЕЕ примерно В ДВА РАЗА.
Вы должны использовать JMH для тестов. Ваш тест действительно неточный.
String неизменяемый.
StringBuffer - это изменяемый и синхронизированный.
StringBuilder также изменчив, но не синхронизирован.
Кроме того, StringBuffer блокирует потоки для доступа к этим потокобезопасным данным, поэтому операция идет медленно. StringBuilder не блокирует потоки и работает в многопоточном режиме, поэтому работает быстро. String - если вам не нужно объединять строку, это хороший способ, но когда вам это нужно, используйте StringBuilder ->, потому что String создает каждый раз новый объект в куче, но StringBuilder возвращает тот же объект ...
Каждый метод, присутствующий в StringBuffer, синхронизируется. следовательно, одновременно только одному потоку разрешено управлять объектом StringBuffer. Увеличивает время ожидания потока и создает проблемы с производительностью. Чтобы решить эту проблему, SUN People представил StringBuilder в версии 1.5.
Поскольку StringBuffer синхронизирован, он требует дополнительных усилий, поэтому, исходя из производительности, он немного медленнее, чем StringBuilder.
Основное различие заключается в том, что StringBuffer синхронизируется, а StringBuilder - нет. Если вам нужно использовать более одного потока, рекомендуется использовать StringBuffer. Но по скорости выполнения StringBuilder быстрее, чем StringBuffer, потому что он не синхронизируется.
StringBuffer является потокобезопасным только в том случае, если вы выполняете с ним только одну операцию. Я бы не рекомендовал использовать его в нескольких потоках, потому что это очень сложно сделать правильно. Большинство применений StringBuffer не являются потокобезопасными, поскольку они совершают несколько обращений к нему без внешней синхронизации, что делает класс бессмысленным.
Сначала давайте посмотрим сходство: И StringBuilder, и StringBuffer изменяемы. Это означает, что вы можете изменить их содержимое в том же месте.
Различия: StringBuffer также изменяемый и синхронизированный. Где как StringBuilder является изменяемым, но не синхронизируется по умолчанию.
Значение synchronized (синхронизация): Когда что-то синхронизируется, тогда несколько потоков могут получить доступ и изменить его без каких-либо проблем или побочных эффектов. StringBuffer синхронизирован, поэтому вы можете использовать его с несколькими потоками без каких-либо проблем.
Какой использовать когда? StringBuilder: когда вам нужна строка, которую можно изменить, и только один поток обращается к ней и изменяет ее. StringBuffer: когда вам нужна строка, которую можно изменить, и несколько потоков обращаются к ней и изменяют ее.
Примечание: не используйте StringBuffer без надобности, т.е. не используйте его, если только один поток модифицирует и получает к нему доступ, потому что у него много кода блокировки и разблокировки для синхронизации, что излишне отнимает время процессора. Не используйте замки, если это не требуется.
Просто хочу упомянуть, что вызовы метода INDIVIDUAL StringBuffer потокобезопасны. Но если у вас есть несколько строк кода, используйте синхронизированный блок кода, чтобы гарантировать потокобезопасность, с некоторой блокировкой / монитором (как обычно ...). По сути, не стоит просто предполагать, что использование потокобезопасной библиотеки сразу же гарантирует безопасность потоков в ВАШЕЙ программе!
Простая программа, иллюстрирующая разницу между StringBuffer и StringBuilder:
/**
* Run this program a couple of times. We see that the StringBuilder does not
* give us reliable results because its methods are not thread-safe as compared
* to StringBuffer.
*
* For example, the single append in StringBuffer is thread-safe, i.e.
* only one thread can call append() at any time and would finish writing
* back to memory one at a time. In contrast, the append() in the StringBuilder
* class can be called concurrently by many threads, so the final size of the
* StringBuilder is sometimes less than expected.
*
*/
public class StringBufferVSStringBuilder {
public static void main(String[] args) throws InterruptedException {
int n = 10;
//*************************String Builder Test*******************************//
StringBuilder sb = new StringBuilder();
StringBuilderTest[] builderThreads = new StringBuilderTest[n];
for (int i = 0; i < n; i++) {
builderThreads[i] = new StringBuilderTest(sb);
}
for (int i = 0; i < n; i++) {
builderThreads[i].start();
}
for (int i = 0; i < n; i++) {
builderThreads[i].join();
}
System.out.println("StringBuilderTest: Expected result is 1000; got " + sb.length());
//*************************String Buffer Test*******************************//
StringBuffer sb2 = new StringBuffer();
StringBufferTest[] bufferThreads = new StringBufferTest[n];
for (int i = 0; i < n; i++) {
bufferThreads[i] = new StringBufferTest(sb2);
}
for (int i = 0; i < n; i++) {
bufferThreads[i].start();
}
for (int i = 0; i < n; i++) {
bufferThreads[i].join();
}
System.out.println("StringBufferTest: Expected result is 1000; got " + sb2.length());
}
}
// Every run would attempt to append 100 "A"s to the StringBuilder.
class StringBuilderTest extends Thread {
StringBuilder sb;
public StringBuilderTest (StringBuilder sb) {
this.sb = sb;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
sb.append("A");
}
}
}
//Every run would attempt to append 100 "A"s to the StringBuffer.
class StringBufferTest extends Thread {
StringBuffer sb2;
public StringBufferTest (StringBuffer sb2) {
this.sb2 = sb2;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
sb2.append("A");
}
}
}
Pretty Good Question
Вот отличия, которые я заметил:
StringBuffer: -
StringBuffer is synchronized
StringBuffer is thread-safe
StringBuffer is slow (try to write a sample program and execute it, it will take more time than StringBuilder)
StringBuilder: -
StringBuilder is not synchronized
StringBuilder is not thread-safe
StringBuilder performance is better than StringBuffer.
Обычное дело: -
Both have same methods with same signatures. Both are mutable.
StringBuffer изменчив. Он может меняться по длине и содержанию. StringBuffers являются потокобезопасными, что означает, что у них есть синхронизированные методы для управления доступом, так что только один поток может получить доступ к синхронизированному коду объекта StringBuffer одновременно. Таким образом, объекты StringBuffer, как правило, безопасно использовать в многопоточной среде, где несколько потоков могут одновременно пытаться получить доступ к одному и тому же объекту StringBuffer.
StringBuilder Класс StringBuilder очень похож на StringBuffer, за исключением того, что его доступ не синхронизирован, поэтому он не является потокобезопасным. Без синхронизации производительность StringBuilder может быть лучше, чем StringBuffer. Таким образом, если вы работаете в однопоточной среде, использование StringBuilder вместо StringBuffer может привести к повышению производительности. Это также верно и для других ситуаций, таких как локальная переменная StringBuilder (т. Е. Переменная внутри метода), где только один поток будет обращаться к объекту StringBuilder.
StringBuffer:
StringBuilder
Точнее, String c = a + b эквивалентен String c = new StringBuilder().append(a).append(b).toString(), поэтому не быстрее. Это только то, что вы создаете новый для каждого назначения строк, в то время как у вас может быть только один (String d = a + b; d = d + c; - это String d = new StringBuilder().append(a).append(b).toString(); d = new StringBuilder().append(d).append(c).toString();, а StringBuilder sb = new StringBuilder(); sb.append(a).append(b); sb.append(c); String d = sb.toString(); сохранит один экземпляр StringBuilder).
Между StringBuilder и StringBuffer нет принципиальных различий, между ними существует лишь несколько различий. В StringBuffer методы синхронизированы. Это означает, что одновременно с ними может работать только один поток. Если существует более одного потока, то второй поток должен будет дождаться завершения первого, а третий - дождаться завершения первого и второго и так далее. Это делает процесс очень медленным и, следовательно, производительность в случае StringBuffer низкая.
С другой стороны, StringBuilder не синхронизируется. Это означает, что одновременно несколько потоков могут работать с одним и тем же объектом StringBuilder одновременно. Это делает процесс очень быстрым и, следовательно, производительность StringBuilder высока.
Проверьте внутреннее устройство синхронизированного метода добавления StringBuffer и несинхронизированного метода добавления StringBuilder.
public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}
public synchronized StringBuffer append(Object obj) {
super.append(String.valueOf(obj));
return this;
}
public synchronized StringBuffer append(String str) {
super.append(str);
return this;
}
public StringBuilder(String str) {
super(str.length() + 16);
append(str);
}
public StringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
public StringBuilder append(String str) {
super.append(str);
return this;
}
Поскольку append - это synchronized, StringBuffer имеет накладные расходы по производительности по сравнению с StrinbBuilder в многопоточном сценарии. Пока вы не разделяете буфер между несколькими потоками, используйте StringBuilder, который работает быстро из-за отсутствия synchronized в методах добавления.
StringBuffer
StringBuffer является изменяемым, что означает, что можно изменить значение объекта. Объект, созданный с помощью StringBuffer, хранится в куче. StringBuffer имеет те же методы, что и StringBuilder, но каждый метод в StringBuffer синхронизирован, то есть StringBuffer является потокобезопасным.
из-за этого он не позволяет двум потокам одновременно обращаться к одному и тому же методу. К каждому методу можно получить доступ по одному потоку за раз.
Но потокобезопасность также имеет недостатки, так как производительность StringBuffer попадает из-за свойства потокобезопасности. Таким образом, StringBuilder быстрее, чем StringBuffer, при вызове одних и тех же методов каждого класса.
Значение StringBuffer можно изменить, то есть присвоить ему новое значение. В настоящее время это самый распространенный вопрос на собеседовании - различия между вышеуказанными классами. String Buffer можно преобразовать в строку с помощью toString () метод.
StringBuffer demo1 = new StringBuffer(“Hello”) ;
// The above object stored in heap and its value can be changed .
demo1=new StringBuffer(“Bye”);
// Above statement is right as it modifies the value which is allowed in the StringBuffer
StringBuilder
StringBuilder аналогичен StringBuffer, то есть хранит объект в куче, и его также можно изменить. Основное различие между StringBuffer и StringBuilder заключается в том, что StringBuilder также не является потокобезопасным. StringBuilder работает быстро, поскольку не является потокобезопасным.
StringBuilder demo2= new StringBuilder(“Hello”);
// The above object too is stored in the heap and its value can be modified
demo2=new StringBuilder(“Bye”);
// Above statement is right as it modifies the value which is allowed in the StringBuilder
Ресурс: Строка против StringBuffer против StringBuilder
StringBuilder является неизменным, а тип String - изменяемым
Я бы не согласился с тем, что Strings и StringBuilders «быстрые», а StringBuffers «очень медленные». См. Ответы выше.
Строитель строк:
int one = 1;
String color = "red";
StringBuilder sb = new StringBuilder();
sb.append("One = ").append(one).append(", Color = ").append(color).append('\n');
System.out.print(sb);
// Prints "One=1, Colour=red" followed by an ASCII newline.
Строка-буфер
StringBuffer sBuffer = new StringBuffer("test");
sBuffer.append(" String Buffer");
System.out.println(sBuffer);
По возможности рекомендуется использовать StringBuilder, потому что он быстрее, чем StringBuffer. Однако, если безопасность потоков необходима, лучшим вариантом являются объекты StringBuffer.
Если вам нужна потокобезопасность, лучшим вариантом является использование StringBuilder, поскольку StringBuffer является потокобезопасным только для отдельных операций. Для нескольких операций нужна явная блокировка.
Вот результат тестирования производительности для Строка против StringBuffer против StringBuilder. Наконец, StringBuilder выиграл тест. Смотрите ниже тестовый код и результат.
Код:
private static void performanceTestStringVsStringbuffereVsStringBuilder() {
// String vs StringBiffer vs StringBuilder performance Test
int loop = 100000;
long start = 0;
// String
String str = null;
start = System.currentTimeMillis();
for (int i = 1; i <= loop; i++) {
str += i + "test";
}
System.out.println("String - " + (System.currentTimeMillis() - start) + " ms");
// String buffer
StringBuffer sbuffer = new StringBuffer();
start = System.currentTimeMillis();
for (int i = 1; i <= loop; i++) {
sbuffer.append(i).append("test");
}
System.out.println("String Buffer - " + (System.currentTimeMillis() - start) + " ms");
// String builder
start = System.currentTimeMillis();
StringBuilder sbuilder = new StringBuilder();
for (int i = 1; i <= loop; i++) {
sbuffer.append(i).append("test");
}
System.out.println("String Builder - " + (System.currentTimeMillis() - start) + " ms");
}
Результат:
100000 итераций для добавления одного текста
String - 37489 ms
String Buffer - 5 ms
String Builder - 4 ms
10000 итераций для добавления одного текста
String - 389 ms
String Buffer - 1 ms
String Builder - 1 ms
Другие правильно указали на ключевые различия между ними. Однако с точки зрения производительности я хотел бы добавить, что оптимизация уровня JVM "Lock Elision", которая могла бы сделать разницу в производительности в контексте синхронизации, практически не существует. Отличное чтение по этому поводу - здесь и здесь.
Разница между StringBuffer и StringBuilder Источник:
а StringBuilder предназначен для замены StringBuffer, где синхронизация не требуется.