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

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

30 ответов


StringBuffer синхронизируется, StringBuilder нет.


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

A


по сути, StringBuffer методы синхронизируются в то время как StringBuilder нет.

операции "почти" одинаковы, но использование синхронизированных методов в одном потоке является излишним.

это в значительной степени об этом.

цитата StringBuilder API:

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

таким образом, он был сделан, чтобы заменить его.

то же самое произошло и с Vector и ArrayList.


но нужно было получить четкое различие с помощью примера?

StringBuffer или StringBuilder

просто использовать StringBuilder Если вы действительно не пытаетесь разделить буфер между потоками. StringBuilder является несинхронизированным (меньше накладных расходов = более эффективным) младшим братом исходного синхронизированного StringBuffer класса.

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

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

С StringBuilder Это drop-in замена на StringBuffer без синхронизации не было бы различий между любыми примерами.

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


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

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

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

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

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


в отдельных потоках,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 take 157 МС для 100000 приложений. Это не тот же тест, но по сравнению с предыдущими 37 МС, вы можете смело предположить, что StringBuffers добавляет медленнее с использованием многопоточности. Причина в том, что JIT/hotspot/compiler/something делает оптимизацию, когда обнаруживает, что есть нет нужен для проверки замков.

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

вывод о том, что вам не придется гоняться StringBuffers. И где у вас есть нити, подумайте о том, что они делают, прежде чем пытаться получить несколько наносекунд.


StringBuilder был представлен в Java 1.5, поэтому он не будет работать с более ранними JVMs.

с Javadocs:

класс StringBuilder предоставляет API, совместимый со StringBuffer, но без гарантии синхронизации. Этот класс предназначен для использования в качестве замены StringBuffer в местах, где строковый буфер использовался одним потоком (как это обычно бывает). По возможности рекомендуется, чтобы этот класс предпочтительнее использовать StringBuffer, так как он будет быстрее в большинстве реализаций.


Очень Хороший Вопрос

вот различия, я заметил:

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.

обычное дело :-

оба имеют одинаковые методы с одинаковыми сигнатурами. Оба изменчивы.


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

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


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

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

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


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

enter image description here

источник: Строка Против StringBuffer Против То StringBuilder


StringBuffer

  • синхронизировано, следовательно, threadsafe
  • thread safe следовательно медленный
  • -

StringBuilder

  • введено в Java 5.0
  • асинхронный, следовательно, быстрым и эффективным!--7-->
  • пользователь явно нужно синхронизировать его, если он хочет
  • вы можете заменить его будет StringBuilder без каких-либо других изменений

String - это неизменяемая.

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

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


на javadoc объясняю разницу:

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


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

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


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

здесь вы получили больше идеи о стоимости синхронизации

пусть взять программно посмотреть, сколько StringBuilder быстрее, чем StringBuffer

public class Test{  
 public static void main(String[] args){  
    long startTime = System.currentTimeMillis();  
    StringBuffer sb = new StringBuffer("Yasir");  
    for (int i=0; i<10000; i++){  
        sb.append("Shabbir");  
    }  
    System.out.println("Time taken by StringBuffer: " + (System.currentTimeMillis() - startTime) + "ms");  
    startTime = System.currentTimeMillis();  
    StringBuilder sb2 = new StringBuilder("Yasir");  
    for (int i=0; i<10000; i++){  
        sb2.append("Shabbir");  
    }  
    System.out.println("Time taken by StringBuilder: " + (System.currentTimeMillis() - startTime) + "ms");  
}  
}  

выход

время, затраченное StringBuffer: 16ms

время, затраченное StringBuilder: 0ms


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

    }
}

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


StringBuffer синхронизируется, но StringBuilder нет. В результате StringBuilder быстрее StringBuffer.


StringBuffer это Мутабельный. Он может меняться с точки зрения длины и содержания. StringBuffers являются потокобезопасными, что означает, что у них есть синхронизированные методы управления доступом, так что только один поток может получить доступ к синхронизированному коду объекта StringBuffer одновременно. Таким образом, объекты StringBuffer обычно безопасны для использования в многопоточной среде, где несколько потоков могут пытаться получить доступ к одному и тому же объекту StringBuffer время.

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


StringBuffer

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

StringBuilder

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


StringBuffer:

  • Multi-Резьбы
  • синхронизироваться
  • медленнее, чем StringBuilder

StringBuilder

  • Одного Потока
  • Не-Синхронизированных
  • быстрее, чем когда-либо строку

Строка-Строителя :

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.

String-Buffer

StringBuffer sBuffer = new StringBuffer("test");
sBuffer.append(" String Buffer");
System.out.println(sBuffer);  

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


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

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


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

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


С StringBuffer синхронизировано, ему нужно дополнительное усилие, следовательно, на основе perforamance, его немного медленнее, чем StringBuilder.


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

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


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


Проверьте внутренности синхронизированного метода добавления 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 in append методы.


эта ссылка позволит вам понять концепции не только StringBuilder и StringBuffer но также их связь и разница с String класса. Это позволит вам понять, когда использовать какой класс. http://www.acquireandinspire.org/2013/01/string-string-builder-string-buffer.html