Різниця між StringBuilder і StringBuffer


1577

У чому головна відмінність між StringBufferі StringBuilder? Чи є якісь проблеми щодо ефективності при вирішенні будь-якого з них?

Відповіді:


1665

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


239
і StringBuilder призначений як крапля заміни StringBuffer, коли синхронізація не потрібна
Joel

95
і синхронізація практично ніколи не потрібна. Якщо хтось хоче синхронізувати на StringBuilder, він може просто оточити весь блок коду синхронізованим (sb) {} на примірник
locka

23
@locka Я б заперечував, що StringBuffer - це ніколи не гарна ідея (якщо у вас немає API, який вимагає цього) vanillajava.blogspot.de/2013/04/…
Пітер Лорі

8
Лише місце, яке я бачу для StringBuffer, - це консоль, подібна до виводу та різної утиліти журналу: багато потоків можуть виводитись у конфлікт. Оскільки ви не хочете, щоб 2 виведення змішувалися ... але зазвичай синхронізація на рівні StringBuffer є занадто низькою, ви хочете синхронізуватись у додатку, як levelm, тому відповідь locka є найкращим, а StringBuffer має бути застарілим. Це заощадило б час перегляду коду для новачків.
Ремі Морін

20
Хороший мнемік для тих, хто змішує ці два - BuFFer був Першим, старшим і тому синхронізованим впровадженням. Новий клас Builder використовує шаблон Builder і є асинхронним.
Датаегек

728

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.


10
Я змінив буквений рядок на щось більше: "швидка коричнева лисиця" і отримав більш цікаві результати. В основному, вони приблизно такі ж швидкі. У мене фактично не вистачило пам’яті, тому мені довелося зняти кілька сімочок. Пояснення: синхронізація оптимізована гарячою точкою. Ви в основному просто вимірюєте час, який потрібно зробити для цього (і, можливо, ще кілька оптимізацій).
Джиллес ван Гурп

7
Попередньо потрібно зігрітися. Цей тест несправедливий для StringBuffer. Також було б добре, якби насправді щось додало. Насправді я перевернув тест і додав випадковий рядок і отримав протилежний тест. Скажемо, що не можна довіряти простим орієнтирам. Протилежне показує, що StringBuffer швидше. 5164 для StringBuilder проти 3699 для StringBuffer hastebin.com/piwicifami.avrasm
ммм

75
Це вперше я бачу --> 0в циклі. Знадобився момент, щоб зрозуміти, що це означає. Це щось, що насправді використовується на практиці замість звичного ...; i > 0; i--синтаксису?
Раймунд Кремер

19
Це i -->насправді дратує синтаксис ... Спочатку я думав, що це стріла через коментарі про мистецтво ASCII.
Самер Пурі

14
Інші закінчують різними результатами: alblue.bandlem.com/2016/04/jmh-stringbuffer-stringbuilder.html . Тести дійсно слід робити з JMH, а не з простим. main()Крім того, ваш орієнтир несправедливий. Розминки немає.
Лукас Едер

249

В основному StringBufferметоди синхронізуються при цьомуStringBuilder їх немає.

Операції «майже» однакові, але використання синхронізованих методів в одному потоці є надмірним.

Це майже про це.

Цитата від API StringBuilder :

Цей клас [StringBuilder] надає API, сумісний зі StringBuffer, але без гарантії синхронізації . Цей клас розроблений для використання в якості замінного для заміни StringBuffer у місцях, де буфер рядків використовувався одним потоком (як це зазвичай буває). Там, де це можливо, рекомендується використовувати цей клас у перевазі StringBuffer, оскільки він буде швидшим у більшості реалізацій.

Тож його було зроблено замінити.

Те саме сталося з Vectorі ArrayList.


1
Також з Hashtableі HashMap.
shmosel

176

Але потрібно було зрозуміти різницю за допомогою прикладу?

StringBuffer або StringBuilder

Просто використовуйте, StringBuilderякщо ви дійсно не намагаєтеся поділити буфер між потоками. StringBuilder- це несинхронізований (менш накладний = ефективніший) молодший брат оригінального синхронізованого StringBufferкласу.

StringBufferприйшов першим. Sun заклопотаний правильністю за будь-яких умов, тому вони зробили це синхронізованим, щоб зробити його безпечним для ниток на всякий випадок.

StringBuilderприйшли пізніше. Більшість застосуваньStringBuffer були однопоточними і без потреби виплачували вартість синхронізації.

Так StringBuilderяк це заміна для випадання дляStringBuffer без синхронізації, то не було б різниці між будь-якими прикладами.

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


14
Перша добра відповідь !! Справа в тому, "якщо ви не
поділитеся

1
дуже детальна відповідь!
Рауль

81

Спочатку давайте побачимо схожість : і StringBuilder, і StringBuffer є змінними. Це означає, що ви можете змінити вміст у них в одному і тому ж місці.

Відмінності : StringBuffer також змінюється і синхронізується. Де StringBuilder не змінюється, але за замовчуванням не синхронізується.

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

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

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


2
Хочеться лише зазначити, що виклики методу StringBuffer INDIVIDUAL методу безпечні для потоків. Але якщо у вас є кілька рядків коду, використовуйте синхронізований блок коду, щоб гарантувати безпеку потоку, з деяким блокуванням / монітором (як зазвичай). В основному, не припускайте, що використання бібліотеки, захищеної від потоку, негайно гарантує безпеку потоку у ВАШІЙ програмі!
Кевін Лі

57

В одиночних потоках 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
Builder: 7!

Таким чином, Builders швидше, ніж буфери, і WAY швидше, ніж з'єднання рядків. Тепер давайте використаємо Виконавця для декількох потоків:

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 / точка доступу / компілятор / щось робить оптимізацію, коли виявляє, що немає необхідності перевіряти блокування.

Але з StringBuilder у вас є java.lang.ArrayIndexOutOfBoundsException , оскільки паралельна нитка намагається додати щось там, де не слід.

Висновок полягає в тому, що вам не доведеться переслідувати StringBuffers. І де у вас є нитки, подумайте, що вони роблять, перш ніж намагатися набрати кілька наносекунд.


5
Ви забули зробити "t0 = System.currentTimeMillis ();" перед тим, як робити тест StringBuilder. Таким чином, показник для StringBuilder - це фактично час, необхідний для запуску тесту stringbuffer AND stringbuilder. Додайте цей рядок, і ви побачите, що StringBuilder швидше на ДВІ ЧАСИ.
Гена Бацян

Зауважте, що withString+="some string"+i+" ; ";це не еквівалентно двом іншим петлям і тому не є справедливим порівнянням.
Дейв Джарвіс

Точне, виправлене. Мислячі струни все ще дуже повільні.
Ніколя Зозол

Чи можете ви пояснити більше, чому підвищення ArrayIndexOutOfBoundsException для StringBuilder
Аліреза Фаттахі

Ви повинні використовувати JMH для орієнтирів. Ваш орієнтир дійсно неточний.
Лукас Едер

42

StringBuilder був представлений на Java 1.5, тому він не працюватиме з більш ранніми JVM.

З Javadocs :

Клас StringBuilder надає API, сумісний зі StringBuffer, але без гарантії синхронізації. Цей клас розроблений для використання в якості замінного для заміни StringBuffer у місцях, де буфер рядків використовувався одним потоком (як це зазвичай буває). Там, де це можливо, рекомендується використовувати цей клас у перевазі StringBuffer, оскільки він буде швидшим у більшості реалізацій.


13
1.4 знаходиться на кінці терміну служби, тому навряд чи варто потурбуватися про попередній 1.5.
Том Хотін - тайклін

@ tomHawtin-tackline не обов'язково - є продукти підприємства на попередньому 1.4, які більшість з нас використовує щодня. Також BlackBerry Java базується на 1.4, і це все ще дуже актуально.
Річард Ле Месюр'є

І CDC, і CLDC не мають StringBuilder.
Джин Квон

37

Досить гарне запитання

Ось відмінності я помітив:

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.

Загальна річ: -

Обидва мають однакові методи з однаковими підписами. Обидва є змінними.


23

StringBuffer

  • Звідси синхронізовані безпечні нитки
  • Нитка безпечна, отже повільна

StringBuilder

  • Введено в Java 5.0
  • Асинхронний, отже, швидкий та ефективний
  • Користувачеві явно потрібно синхронізувати його, якщо він хоче
  • Ви можете замінити його StringBufferбез будь-яких інших змін

ПРИМІТКА. Лише одні операції є безпечними для потоків, кілька операцій не є. наприклад , якщо ви телефонуєте в appendдва рази, або appendі toStringНЕ небезпечно.
Пітер Лорі

22

StringBuilder не є безпечним для потоків. Строковий буфер є. Більше інформації тут .

EDIT: Що стосується продуктивності, після того, як гаряча точка починається, StringBuilder є переможцем. Однак для невеликих ітерацій різниця в продуктивності незначна.


21

StringBuilderі StringBufferмайже однакові. Різниця в тому, що StringBufferсинхронізовано і StringBuilderні. Хоча, StringBuilderшвидше, ніж StringBufferрізниця в продуктивності дуже мала. StringBuilderє заміною SUN StringBuffer. Це просто уникає синхронізації з усіх публічних методів. Замість цього їх функціональність однакова.

Приклад вдалого використання:

Якщо ваш текст буде змінено і використовується декількома нитками, тоді краще використовувати StringBuffer. Якщо ваш текст буде змінено, але він використовується однією ниткою, тоді використовуйте StringBuilder.


19

StringBuffer

StringBuffer є змінним - це означає, що можна змінити значення об'єкта. Об'єкт, створений через StringBuffer, зберігається у купі. StringBuffer має ті ж методи, що і StringBuilder, але кожен метод у StringBuffer синхронізований, тобто StringBuffer є безпечним для потоків.

через це він не дозволяє двом потокам одночасно отримати доступ до одного методу. Кожен метод може отримати доступ по одній нитці одночасно.

Але безпека для потоків має і недоліки, як і ефективність звернень StringBuffer завдяки властивості безпечного потоку. Таким чином, StringBuilder швидше, ніж StringBuffer, коли викликає однакові методи кожного класу.

Значення StringBuffer можна змінити, це означає, що воно може бути присвоєне новому значенню. В даний час найпоширенішим питанням для інтерв'ю є відмінності між вищезазначеними класами. Строковий буфер можна перетворити в рядок за допомогою методу 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

введіть тут опис зображення

Ресурс: String Vs StringBuffer Vs StringBuilder


StringBuilder незмінний, а тип струнного - мінливий
Brinda Rathod

Я не погоджуюся, що Strings і StringBuilders "швидкі", а StringBuffers - "дуже повільні". Дивіться вищевказані відповіді.
FireCubez

17

String є незмінним.

StringBuffer є мутаційним та синхронізованим.

StringBuilder також є змінним, але не синхронізований.


Крім того, StringBuffer блокує нитки для доступу до цих потоків безпечних даних, тому робота йде повільно. StringBuilder не блокує нитку, і вона працює в режимі Multi Threading, тому це швидко. String - коли вам не потрібно об'єднувати рядок, це хороший спосіб, але коли вам це потрібно, використовуйте StringBuilder -> тому що String створює кожен раз новий об'єкт у купі, але StringBuilder повертає той самий об'єкт ...
Musa

11

Javadoc пояснює різницю:

Цей клас надає API, сумісний зі StringBuffer, але без гарантії синхронізації. Цей клас розроблений для використання в якості замінного для заміни StringBuffer у місцях, де буфер рядків використовувався одним потоком (як це зазвичай буває). Там, де це можливо, рекомендується використовувати цей клас у перевазі StringBuffer, оскільки він буде швидшим у більшості реалізацій.


10

StringBuilder (введено в Java 5) ідентично StringBuffer , за винятком того, що його методи не синхронізовані. Це означає, що він має кращі показники, ніж останні, але недолік у тому, що він не є безпечним для потоків.

Прочитайте підручник для більш детальної інформації.


6

Проста програма, що ілюструє різницю між 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");
        }

    }
}

4

StringBuffer використовується для зберігання символьних рядків, які будуть змінені (String-об'єкти неможливо змінити). Він автоматично розширюється за потреби. Суміжні класи: String, CharSequence.

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


4
Однопотокові програми - не найпоширеніший випадок на Java, але StringBuilderзазвичай ‍ локальний для методу, де вони видно лише одному потоку.
finnw

4

StringBufferсинхронізовано, але StringBuilderце не так. Як результат, StringBuilderшвидше, ніж StringBuffer.


4

StringBuffer змінюється. Він може змінюватися з точки зору тривалості та змісту. StringBuffers безпечні для потоків, тобто вони мають синхронізовані методи управління доступом, щоб лише один потік одночасно мав доступ до синхронізованого коду об'єкта StringBuffer. Таким чином, об'єкти StringBuffer, як правило, безпечні для використання у багатопотоковому середовищі, де кілька потоків можуть намагатися отримати доступ до того ж об’єкта StringBuffer одночасно.

StringBuilder Клас StringBuilder дуже схожий на StringBuffer, за винятком того, що його доступ не синхронізований, щоб він не був безпечним для потоків. Не синхронізуючись, продуктивність StringBuilder може бути кращою, ніж StringBuffer. Таким чином, якщо ви працюєте в однопотоковому середовищі, використання StringBuilder замість StringBuffer може призвести до підвищення продуктивності. Це також стосується інших ситуацій, таких як локальна змінна StringBuilder (тобто змінна в межах методу), коли лише один потік матиме доступ до об’єкта StringBuilder.


4

StringBuffer:

  • Багатониткова
  • Синхронізовано
  • Повільніше, ніж StringBuilder

StringBuilder

  • Однотонна
  • Не синхронізований
  • Швидше, ніж будь-коли струна

2
Точніше, 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).
Чоп

4

String-Builder :

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 безпечний лише для ниток для окремих операцій. Для декількох операцій потрібно чітке блокування.
Пітер Лорі

4

Краще використовувати, StringBuilderоскільки він не синхронізований, а тому забезпечує кращі показники. StringBuilder- це заміна заміни старшого StringBuffer.


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

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

3

Так як StringBufferсинхронізація, вона потребує в деяких додаткових зусиль, отже , на основі perforamance, його трохи повільно ніж StringBuilder.


3

Там немає принципових відмінностей між StringBuilderі StringBuffer, лише кілька відмінностей між ними існують. У StringBufferметодах синхронізовані. Це означає, що одночасно над ними може працювати лише одна нитка. Якщо є більше однієї нитки, то другий потік повинен буде зачекати, коли перший закінчить, а третій повинен буде дочекатися закінчення першого та другого тощо. Це робить процес дуже повільним, а отже, продуктивність у випадку StringBufferнизької.

З іншого боку, StringBuilderне синхронізований. Це означає, що одночасно на одному StringBuilderоб’єкті можуть працювати одночасно кілька потоків . Це робить процес дуже швидким і, отже, ефективність роботи StringBuilderвисока.


3

A Stringє незмінним об'єктом, що означає, що значення не може бути змінено, тоді як StringBufferє змінним.

StringBufferСинхронізований , отже , поточно-то StringBuilderнемає і підходить тільки для однопоточних примірників.


3
тільки тому, що StringBuffer має синхронізований код, не обов'язково означає, що StringBuffer є безпечним для потоків. Розглянемо наступний приклад: StringBuffer testingBuffer = "stackoverflow"; Тепер Thread-1 намагається додати "1" до testingBuffer, а Thread-2 намагається додати "2" до testingBuffer. Тепер навіть незважаючи на те, що метод append () синхронізований, ви не можете бути впевнені, чи буде значення testBuffer "stackoverflow12" або "stackoverflow21". Власне, Oracle радить використовувати stringbuilder над stringbuffer. Сподіваюсь, це допомогло :)
Біман Трипатій

2

Основна відмінність - StringBufferце синхронізована, але StringBuilderце не так. Якщо вам потрібно використовувати більше ніж один потік, то рекомендується StringBuffer. Але на швидкість виконання StringBuilderшвидше StringBuffer, тому що вона не синхронізована.


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

@PeterLawrey, що ти маєш на увазі? :-)
Тамад Ланг

1
@ b16db0 Я маю на увазі, що більшість застосувань StringBuffer не є безпечними для потоків, оскільки вони здійснюють безліч викликів до нього без зовнішньої синхронізації, що робить клас досить безглуздим.
Пітер Лорі

@PeterLawrey ах, це як StringBuffer все ще потребує синхронізованого середовища.
Тамад Ланг

2

Перевірте внутрішні методи синхронізованого способу додавання 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;
}

Оскільки додавання є synchronized, StringBufferефективність перевищує порівняно зі StrinbBuilderсценарієм з багатопотоковою резьбою. Поки ви не поділяєте буфер між декількома потоками, використовуйте StringBuilder, що швидко через відсутність synchronizedметодів додавання.


1

Ось результат тестування продуктивності для String vs StringBuffer vs 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");

  }

Виконати мене на ideone

Результат :

100000 ітерацій для додавання одного тексту

String - 37489 ms
String Buffer - 5 ms
String Builder - 4 ms

10000 ітерацій для додавання одного тексту

String - 389 ms
String Buffer - 1 ms
String Builder - 1 ms

1
  • StringBuffer безпечний для потоків, але StringBuilder не є безпечним для потоків.
  • StringBuilder швидше, ніж StringBuffer.
  • StringBuffer синхронізований, тоді як StringBuilder не синхронізований.

1

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


Ця різниця була вказана у всіх інших відповідях на це питання. Не могли б ви виділити щось нове?
Ніко Хааз
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.