Разница между StringBuilder и StringBuffer

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

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1 632
0
822 921
32
Перейти к ответу Данный вопрос помечен как решенный

Ответы 32

Ответ принят как подходящий

StringBuffer синхронизирован, StringBuilder нет.

а StringBuilder предназначен для замены StringBuffer, где синхронизация не требуется.

Joel 23.12.2009 11:52

и синхронизация практически не требуется. Если кто-то хочет синхронизировать StringBuilder, он может просто окружить весь блок кода синхронизированным (sb) {} на экземпляре.

locka 24.04.2013 20:06

@locka Я бы сказал, что StringBuffer никогда не бывает хорошей идеей (если у вас нет API, который этого требует) vanillajava.blogspot.de/2013/04/…

Peter Lawrey 04.09.2013 14:21

Единственное место, где я вижу StringBuffer, - это консольный вывод и различные утилиты для ведения журнала: многие потоки могут выводить конфликт. Поскольку вы не хотите, чтобы 2 вывода смешивались ... но обычно синхронизация на уровне StringBuffer слишком низка, вы захотите синхронизировать в приложении, таком как levelm, поэтому ответ locka является лучшим, а StringBuffer должен быть устаревшим. Это сэкономит время на проверку кода новичкам.

Remi Morin 17.02.2014 20:10
javahungry.blogspot.com/2013/06/…
Praveen P Moolekandathil 29.05.2015 13:03

Хорошая мнемоника для тех, кто смешивает эти два - BuFFer был первой, более старой и, следовательно, синхронизированной реализацией. Новый класс Builder использует шаблон Builder и является асинхронным.

Datageek 16.01.2016 20:50

Но StringBuffer медленнее, чем StringBuilder. Вы выбираете тот, который вам больше нравится, в зависимости от того, над какими приложениями вы работаете.

tqjustc 26.03.2016 02:05

Другое отличие состоит в том, что StringBuffer можно использовать с Matcher#appendReplacement, тогда как StringBuilderне могу. Это очень неприятная разница в API, особенно потому, что Matcher не является потокобезопасным, поэтому для appendReplacement нет необходимости требовать синхронизации.

Max 15.04.2016 00:10

Чтобы найти более подробную информацию о том, какова фактическая причина сбоя StringBuilder в многопоточной среде, я задал вопрос, который может быть полезным stackoverflow.com/questions/31375718/…

Alireza Fattahi 21.12.2016 13:06

Почему в последней редакции говорится, что StringBuilder является неизменяемым объектом? Он не является неизменным и не является объектом, это класс. Это не должно быть частью основного ответа.

Raimund Krämer 09.11.2017 11:21

@ D.Everhard Согласился, вообще-то я тоже запутался. Это нужно исправить.

foxt7ot 16.11.2017 18:43

@sblundy StringBuilder не является неизменным, шокирован, поскольку никто не указал

DnA 17.11.2017 20:54

StringBuffer выполняется быстрее, чем StringBuilder.

N.Chandimali 11.03.2018 21:33

В основном методы 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.

shmosel 17.03.2017 22:14

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.

Tom Hawtin - tackline 14.12.2008 20:15

@ tomHawtin-tackline не обязательно - есть корпоративные продукты до 1.4, которые большинство из нас использует ежедневно. Также BlackBerry java основана на 1.4, и она все еще очень актуальна.

Richard Le Mesurier 13.03.2013 12:47

И CDC, и CLDC не имеют StringBuilder.

Jin Kwon 12.07.2013 07:47

StringBuilder не является потокобезопасным. Строковый буфер есть. Подробнее здесь.

Обновлено: Что касается производительности, после того, как горячая точка срабатывает, StringBuilder становится победителем. Однако для небольших итераций разница в производительности незначительна.

StringBuffer

  • Синхронизирован, следовательно, безопасен для потоков
  • Потоковая безопасность, следовательно, медленная

StringBuilder

  • Представлено в Java 5.0
  • Асинхронный, следовательно, быстрый и эффективный
  • Пользователь явно должен синхронизировать его, если он хочет
  • Вы можете заменить его на StringBuffer без каких-либо других изменений

ПРИМЕЧАНИЕ. Только одиночные операции являются потокобезопасными, а множественные - нет. например, если вы дважды звоните append или append и toString небезопасны.

Peter Lawrey 13.01.2019 13:30

StringBuffer используется для хранения символьных строк, которые будут изменены (объекты String не могут быть изменены). Он автоматически расширяется по мере необходимости. Связанные классы: String, CharSequence.

StringBuilder был добавлен в Java 5. Он во всех отношениях идентичен StringBuffer, за исключением того, что он не синхронизирован, что означает, что если несколько потоков обращаются к нему одновременно, могут возникнуть проблемы. Для однопоточных программ, наиболее распространенный случай, когда исключение накладных расходов на синхронизацию делает StringBuilder немного быстрее.

Однопоточные программы - не самый распространенный случай в Java, но StringBuilder обычно являются локальными для метода, где они видны только одному потоку.

finnw 25.01.2011 17:36

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.

Я изменил строковый литерал на что-то большее: «быстрая коричневая лиса» и получил более интересные результаты. В основном они примерно такие же быстрые. На самом деле у меня закончилась память, поэтому пришлось удалить несколько семерок. Объяснение: синхронизация оптимизирована от точки доступа. По сути, вы просто измеряете время, необходимое точке доступа для этого (и, возможно, еще несколько оптимизаций).

Jilles van Gurp 26.08.2012 19:25

Согласитесь с Альфредо. Добавление к комментарию Jiles, когда используется с одной строкой символов ("A"), соотношение будет как 2 x 1 (2 для StringBuffer). используя более 3 символов, и я получил "OutOfMemoryError"! (-Xms512m / -Xmx1024m)

Ricardo Rivaldo 02.04.2013 18:27

Перед тем как разогреться. Этот тест несправедлив к StringBuffer. Кроме того, было бы хорошо, если бы он действительно что-то добавлял. Фактически, я перевернул тест, добавил случайную строку и получил противоположный тест. Можно сказать, что простым тестам доверять нельзя. Напротив, StringBuffer работает быстрее. 5164 для StringBuilder и 3699 для StringBuffer hastebin.com/piwicifami.avrasm

mmm 03.11.2015 14:34

Если кто-то пытается запускать тесты снова и снова, в разном порядке, разница едва заметна, и, откровенно говоря, не ясно, кто победит.

mmm 03.11.2015 14:47

Это первый раз, когда я вижу --> 0 в петле. Мне потребовалось время, чтобы понять, что это значит. Это то, что действительно используется на практике вместо обычного синтаксиса ...; i > 0; i--?

Raimund Krämer 15.12.2015 15:25

Да, даже я не использовал такое для конструкций -> 0, я пробовал использовать {for (int i = 0; i --> N ;)}, который не работал? .

avinashkr 02.08.2016 12:13

Этот i --> действительно раздражает с точки зрения синтаксиса ... Сначала я подумал, что это стрелка из-за комментариев об искусстве ASCII.

Sameer Puri 10.08.2016 22:14

@ D.Everhard и другие: Этот может быть для вас интересным чтением.

Adowrath 30.01.2017 01:07

Другие заключают с другими результатами: alblue.bandlem.com/2016/04/jmh-stringbuffer-stringbuilder.ht‌ мл. Тесты действительно должны выполняться с JMH, а не с простым main(). Кроме того, ваш тест несправедлив. Нет никакой разминки.

Lukas Eder 02.06.2017 12:03

какой был бы прекрасный мир, если бы for (int i = N; i --> 0 ;) засчитали как трюк для вечеринки

lelloman 19.06.2017 11:00

Этот тест неточен, когда код находится внутри первой лупы, JVM необходимо загружать массивы изнутри, поскольку они используются внутри самого конструктора строк, но он не делает этого в тесте de stringbuilder, поскольку он уже загрузил его.

Ferrybig 15.02.2019 18:47

String - это неизменяемый объект, что означает, что значение не может быть изменено, тогда как StringBuffer является изменяемым.

StringBuffer синхронизирован, следовательно, потокобезопасен, тогда как StringBuilder нет и подходит только для однопоточных экземпляров.

просто потому, что StringBuffer имеет синхронизированный код, не обязательно означает, что StringBuffer является потокобезопасным. Рассмотрим следующий пример: StringBuffer testingBuffer = "stackoverflow"; Теперь Thread-1 пытается добавить «1» к testBuffer, а Thread-2 пытается добавить «2» к testingBuffer. Теперь, несмотря на то, что метод append () синхронизирован, вы не можете быть уверены, будет ли значение testingBuffer «stackoverflow12» или «stackoverflow21». На самом деле Oracle рекомендует использовать построитель строк вместо буфера строк. Надеюсь, это помогло :)

Biman Tripathy 26.12.2012 01:29

StringBuilder и StringBuffer почти одинаковы. Разница в том, что StringBuffer синхронизирован, а StringBuilder - нет. Хотя StringBuilder быстрее, чем StringBuffer, разница в производительности очень небольшая. StringBuilder - это замена StringBuffer SUN. Он просто избегает синхронизации со всеми общедоступными методами. Скорее, их функциональность такая же.

Пример правильного использования:

Если ваш текст будет изменяться и используется несколькими потоками, то лучше использовать StringBuffer. Если ваш текст будет изменяться, но используется одним потоком, используйте StringBuilder.

Лучше использовать StringBuilder, так как он не синхронизированный и, следовательно, обеспечивает лучшую производительность. StringBuilder - это безотказная замена более старого StringBuffer.

Если, конечно, ваше приложение не является многопоточным. :)

Mark McKenna 25.01.2011 15:23

@Mark true, но в большинстве случаев StringBu(ff|ild)er - это локальная переменная, используемая только одним потоком.

gabuzo 25.01.2011 15:25

@MarkMcKenna: даже в многопоточном приложении часто приходилось либо использовать внешнюю блокировку, либо делать дополнительную работу, чтобы ее избежать. Например, если два потока хотят добавить запись, содержащую несколько строк, в построитель строк, им придется агрегировать данные, которые нужно добавить, а затем добавить их как единое целое, даже если это было бы быстрее - при отсутствии проблем с потоками - просто выполнить последовательность дискретных операций добавления.

supercat 13.03.2014 19:54

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.

Первый хороший ответ !! Дело в том, что «если вы не разделяете буфер между потоками»

AlexWien 20.03.2015 20:47

В одиночных потоках - 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 БЫСТРЕЕ примерно В ДВА РАЗА.

Gena Batsyan 26.09.2013 13:51

Вы должны использовать JMH для тестов. Ваш тест действительно неточный.

Lukas Eder 02.06.2017 12:21

String неизменяемый.

StringBuffer - это изменяемый и синхронизированный.

StringBuilder также изменчив, но не синхронизирован.

Кроме того, StringBuffer блокирует потоки для доступа к этим потокобезопасным данным, поэтому операция идет медленно. StringBuilder не блокирует потоки и работает в многопоточном режиме, поэтому работает быстро. String - если вам не нужно объединять строку, это хороший способ, но когда вам это нужно, используйте StringBuilder ->, потому что String создает каждый раз новый объект в куче, но StringBuilder возвращает тот же объект ...

Musa 01.03.2018 00:46

Каждый метод, присутствующий в StringBuffer, синхронизируется. следовательно, одновременно только одному потоку разрешено управлять объектом StringBuffer. Увеличивает время ожидания потока и создает проблемы с производительностью. Чтобы решить эту проблему, SUN People представил StringBuilder в версии 1.5.

Поскольку StringBuffer синхронизирован, он требует дополнительных усилий, поэтому, исходя из производительности, он немного медленнее, чем StringBuilder.

Основное различие заключается в том, что StringBuffer синхронизируется, а StringBuilder - нет. Если вам нужно использовать более одного потока, рекомендуется использовать StringBuffer. Но по скорости выполнения StringBuilder быстрее, чем StringBuffer, потому что он не синхронизируется.

StringBuffer является потокобезопасным только в том случае, если вы выполняете с ним только одну операцию. Я бы не рекомендовал использовать его в нескольких потоках, потому что это очень сложно сделать правильно. Большинство применений StringBuffer не являются потокобезопасными, поскольку они совершают несколько обращений к нему без внешней синхронизации, что делает класс бессмысленным.

Peter Lawrey 17.12.2013 14:59

Сначала давайте посмотрим сходство: И StringBuilder, и StringBuffer изменяемы. Это означает, что вы можете изменить их содержимое в том же месте.

Различия: StringBuffer также изменяемый и синхронизированный. Где как StringBuilder является изменяемым, но не синхронизируется по умолчанию.

Значение synchronized (синхронизация): Когда что-то синхронизируется, тогда несколько потоков могут получить доступ и изменить его без каких-либо проблем или побочных эффектов. StringBuffer синхронизирован, поэтому вы можете использовать его с несколькими потоками без каких-либо проблем.

Какой использовать когда? StringBuilder: когда вам нужна строка, которую можно изменить, и только один поток обращается к ней и изменяет ее. StringBuffer: когда вам нужна строка, которую можно изменить, и несколько потоков обращаются к ней и изменяют ее.

Примечание: не используйте StringBuffer без надобности, т.е. не используйте его, если только один поток модифицирует и получает к нему доступ, потому что у него много кода блокировки и разблокировки для синхронизации, что излишне отнимает время процессора. Не используйте замки, если это не требуется.

Просто хочу упомянуть, что вызовы метода INDIVIDUAL StringBuffer потокобезопасны. Но если у вас есть несколько строк кода, используйте синхронизированный блок кода, чтобы гарантировать потокобезопасность, с некоторой блокировкой / монитором (как обычно ...). По сути, не стоит просто предполагать, что использование потокобезопасной библиотеки сразу же гарантирует безопасность потоков в ВАШЕЙ программе!

Kevin Lee 14.03.2014 22:39

Простая программа, иллюстрирующая разницу между 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

StringBuilder

  • Однопоточный
  • Несинхронизированный
  • Быстрее, чем когда-либо String

Точнее, 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).

Chop 24.10.2015 19:50

Между StringBuilder и StringBuffer нет принципиальных различий, между ними существует лишь несколько различий. В StringBuffer методы синхронизированы. Это означает, что одновременно с ними может работать только один поток. Если существует более одного потока, то второй поток должен будет дождаться завершения первого, а третий - дождаться завершения первого и второго и так далее. Это делает процесс очень медленным и, следовательно, производительность в случае StringBuffer низкая.

С другой стороны, StringBuilder не синхронизируется. Это означает, что одновременно несколько потоков могут работать с одним и тем же объектом StringBuilder одновременно. Это делает процесс очень быстрым и, следовательно, производительность StringBuilder высока.

Проверьте внутреннее устройство синхронизированного метода добавления StringBuffer и несинхронизированного метода добавления StringBuilder.

StringBuffer:

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;
}

StringBuilder:

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 - изменяемым

Brinda Rathod 15.10.2018 14:37

Я бы не согласился с тем, что Strings и StringBuilders «быстрые», а StringBuffers «очень медленные». См. Ответы выше.

FireCubez 16.02.2019 17:55

Строитель строк:

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 является потокобезопасным только для отдельных операций. Для нескольких операций нужна явная блокировка.

Peter Lawrey 13.01.2019 13:34

Вот результат тестирования производительности для Строка против 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
  • StringBuffer является потокобезопасным, но StringBuilder не является потокобезопасным.
  • StringBuilder быстрее, чем StringBuffer.
  • StringBuffer синхронизируется, а StringBuilder - нет. синхронизировано.

Другие правильно указали на ключевые различия между ними. Однако с точки зрения производительности я хотел бы добавить, что оптимизация уровня JVM "Lock Elision", которая могла бы сделать разницу в производительности в контексте синхронизации, практически не существует. Отличное чтение по этому поводу - здесь и здесь.

Разница между StringBuffer и StringBuilder Источник:

Другие вопросы по теме