Я нашел интересный ответ для сравнения производительности String vs StringBuffer Реджи Хатчерсо
Источник : http://www.javaworld.com/javaworld/jw-03-2000/jw-0324-javaperf.html
Java предоставляет классы StringBuffer и String, а класс String используется для манипулирования строками символов, которые нельзя изменить. Проще говоря, объекты типа String доступны только для чтения и неизменны. Класс StringBuffer используется для представления символов, которые могут быть изменены.
Существенная разница в производительности между этими двумя классами заключается в том, что StringBuffer быстрее, чем String, при выполнении простых конкатенаций. В коде манипуляции со строками символьные строки обычно объединяются. Используя класс String, конкатенации обычно выполняются следующим образом:
String str = new String ("Stanford ");
str += "Lost!!";
Если бы вы использовали StringBuffer для выполнения той же конкатенации, вам понадобился бы код, который выглядит следующим образом:
StringBuffer str = new StringBuffer ("Stanford ");
str.append("Lost!!");
Разработчики обычно предполагают, что первый пример выше более эффективен, поскольку считают, что второй пример, использующий метод добавления для конкатенации, является более дорогостоящим, чем первый пример, в котором используется оператор + для объединения двух объектов String.
Оператор + выглядит невинным, но сгенерированный код вызывает некоторые сюрпризы. Использование StringBuffer для конкатенации может фактически создать код, который значительно быстрее, чем использование String. Чтобы выяснить, почему это так, мы должны изучить сгенерированный байт-код из наших двух примеров. Байт-код для примера с использованием String выглядит следующим образом:
0 new #7 <Class java.lang.String>
3 dup
4 ldc #2 <String "Stanford ">
6 invokespecial #12 <Method java.lang.String(java.lang.String)>
9 astore_1
10 new #8 <Class java.lang.StringBuffer>
13 dup
14 aload_1
15 invokestatic #23 <Method java.lang.String valueOf(java.lang.Object)>
18 invokespecial #13 <Method java.lang.StringBuffer(java.lang.String)>
21 ldc #1 <String "Lost!!">
23 invokevirtual #15 <Method java.lang.StringBuffer append(java.lang.String)>
26 invokevirtual #22 <Method java.lang.String toString()>
29 astore_1
Байт-код в позициях с 0 по 9 выполняется для первой строки кода, а именно:
String str = new String("Stanford ");
Затем выполняется байт-код в ячейках с 10 по 29 для объединения:
str += "Lost!!";
Здесь все становится интереснее. Байт-код, сгенерированный для конкатенации, создает объект StringBuffer, затем вызывает его метод добавления: временный объект StringBuffer создается в местоположении 10, а его метод добавления вызывается в местоположении 23. Поскольку класс String является неизменяемым, необходимо использовать StringBuffer для конкатенация.
После выполнения объединения объекта StringBuffer его необходимо преобразовать обратно в строку. Это делается с помощью вызова метода toString в местоположении 26. Этот метод создает новый объект String из временного объекта StringBuffer. Создание этого временного объекта StringBuffer и его последующее преобразование обратно в объект String очень дороги.
В итоге, две строки кода выше приводят к созданию трех объектов:
- Объект String в местоположении 0
- Объект StringBuffer в местоположении 10
- Объект String в локации 26
Теперь давайте посмотрим на байт-код, сгенерированный для примера с использованием StringBuffer:
0 new #8 <Class java.lang.StringBuffer>
3 dup
4 ldc #2 <String "Stanford ">
6 invokespecial #13 <Method java.lang.StringBuffer(java.lang.String)>
9 astore_1
10 aload_1
11 ldc #1 <String "Lost!!">
13 invokevirtual #15 <Method java.lang.StringBuffer append(java.lang.String)>
16 pop
Байт-код в ячейках с 0 по 9 выполняется для первой строки кода:
StringBuffer str = new StringBuffer("Stanford ");
Затем выполняется байт-код в ячейках с 10 по 16 для объединения:
str.append("Lost!!");
Обратите внимание, что, как и в первом примере, этот код вызывает метод append объекта StringBuffer. Однако, в отличие от первого примера, нет необходимости создавать временный StringBuffer и затем преобразовывать его в объект String. Этот код создает только один объект, StringBuffer, в местоположении 0.
В заключение, конкатенация StringBuffer значительно быстрее, чем конкатенация String. Очевидно, что StringBuffers следует использовать в этом типе операций, когда это возможно. Если требуется функциональность класса String, рассмотрите возможность использования StringBuffer для объединения, а затем выполните одно преобразование в String.