Разница изменчивости:
String
является неизменным , если вы пытаетесь изменить их значения, создается другой объект, тогда как StringBuffer
и StringBuilder
являются изменяемыми, чтобы они могли изменять свои значения.
Разница в безопасности потоков:
Разница между StringBuffer
и в StringBuilder
том, что StringBuffer
потокобезопасен. Поэтому, когда приложение необходимо запустить только в одном потоке, его лучше использовать StringBuilder
. StringBuilder
более эффективен, чем StringBuffer
.
Ситуации:
- Если ваша строка не будет меняться, используйте класс String, потому что
String
объект неизменен.
- Если ваша строка может измениться (пример: множество логики и операций при построении строки) и будет доступна только из одного потока, достаточно использовать a
StringBuilder
.
- Если ваша строка может измениться и будет доступна из нескольких потоков, используйте
StringBuffer
потому что StringBuffer
является синхронным, чтобы обеспечить безопасность потоков.
Strings
когда мы изменяем значение, создается другой объект. Обнуляется ли старая ссылка на объект, чтобы она могла быть собрана сборщиком мусораGC
или даже сборщиком мусора?String
сStringBuilder
?String
когда неизменяемая структура подходит; получение новой символьной последовательности изString
может привести к неприемлемому снижению производительности, как во время ЦП, так и в памяти (получение подстрок эффективно при использовании ЦП, поскольку данные не копируются, но это означает, что потенциально гораздо больший объем данных может остаться выделенным).StringBuilder
когда вам нужно создать изменяемую последовательность символов, обычно для объединения нескольких последовательностей символов вместе.StringBuffer
в тех же условиях, что и при использованииStringBuilder
, но когда изменения в базовой строке должны быть синхронизированы (потому что несколько потоков читают / модифицируют строковый буфер).Смотрите пример здесь .
источник
Основы:
String
это неизменный класс, его нельзя изменить.StringBuilder
является изменяемым классом, который можно добавлять, заменять или удалять символы и в конечном итоге преобразовыватьString
StringBuffer
в исходную синхронизированную версиюStringBuilder
Вы должны предпочитать
StringBuilder
во всех случаях, когда у вас есть только один поток доступа к вашему объекту.Детали:
Также обратите внимание, что
StringBuilder/Buffers
это не магия, они просто используют Array в качестве вспомогательного объекта и что Array необходимо перераспределять, когда он заполнен. Будьте уверены, и создавайте вашиStringBuilder/Buffer
объекты достаточно большими, чтобы их не приходилось постоянно менять каждый раз при.append()
вызове.Изменение размеров может стать очень вырожденным. Он в основном изменяет размеры резервного массива в 2 раза по сравнению с его текущим размером каждый раз, когда его необходимо расширить. Это может привести к тому, что большие объемы ОЗУ выделяются и не используются, когда
StringBuilder/Buffer
классы начинают расти.В Java
String x = "A" + "B";
используетсяStringBuilder
негласно. Так что для простых случаев нет смысла декларировать свое собственное. Но если вы создаетеString
объекты большого размера, скажем, менее 4 КБ, тогда объявлениеStringBuilder sb = StringBuilder(4096);
намного эффективнее, чем конкатенация или использование конструктора по умолчанию, который состоит всего из 16 символов. Если у васString
будет меньше 10 КБ, инициализируйте его конструктором до 10 КБ, чтобы быть в безопасности. Но если он инициализируется до 10 КБ, то вы записываете на 1 символ больше 10 КБ, он будет перераспределен и скопирован в массив из 20 КБ. Так что инициализация высокого лучше, чем низкого.В случае автоматического изменения размера, у 17-го символа резервный массив перераспределяется и копируется в 32 символа, у 33-го это происходит снова, и вы перераспределяете и копируете массив в 64 символа. Вы можете видеть, как это вырождается во многих перераспределениях и копиях, и это то, что вы действительно стараетесь избегать
StringBuilder/Buffer
в первую очередь.Это из исходного кода JDK 6 для AbstractStringBuilder
Лучшая практика - инициализировать
StringBuilder/Buffer
немного больше, чем вам нужно, если вы не знаете сразу, насколько великString
будет, но вы можете догадаться. Одно выделение чуть больше памяти, чем вам нужно, будет лучше, чем много перераспределений и копий.Также остерегайтесь инициализации
StringBuilder/Buffer
с помощьюString
символа as, который будет выделять только размер строки String + 16, что в большинстве случаев просто начнет вырожденный цикл перераспределения и копирования, которого вы пытаетесь избежать. Следующее прямо из исходного кода Java 6.Если вы случайно столкнулись с экземпляром,
StringBuilder/Buffer
который вы не создали и не можете контролировать вызываемый конструктор, есть способ избежать вырожденного поведения перераспределения и копирования. Позвоните.ensureCapacity()
с размером, который вы хотите, чтобы ваш результатString
соответствовал.Альтернативы:
В качестве примечания, если вы делаете действительно тяжелое
String
построение и манипулирование, есть гораздо более ориентированная на производительность альтернатива, называемая Веревками .Другой альтернативой является создание
StringList
реализации путем подклассаArrayList<String>
и добавления счетчиков для отслеживания количества символов в каждой.append()
и других операциях мутации в списке, а затем переопределения.toString()
для созданияStringBuilder
нужного вам размера, циклического перемещения по списку и построения. вывод, вы даже можете сделатьStringBuilder
это экземпляром переменной и «кэшировать» результаты,.toString()
и вам нужно будет только сгенерировать его, когда что-то изменится.Также не забывайте о
String.format()
создании фиксированного форматированного вывода, который может быть оптимизирован компилятором, так как он делает его лучше.источник
String x = "A" + "B";
Действительно ли компилируется, чтобы быть StringBuilder? Почему бы просто не скомпилироватьString x = "AB";
, он должен использовать только StringBuilder, если компоненты не известны во время компиляции.Вы имеете в виду, для объединения?
Пример из реального мира: вы хотите создать новую строку из множества других .
Например, чтобы отправить сообщение:
строка
StringBuilder
Или
StringBuffer (синтаксис такой же, как и у StringBuilder, эффекты отличаются)
Около
StringBuffer
противStringBuilder
Первый синхронизирован, а позже нет.
Таким образом, если вы вызываете его несколько раз в одном потоке (что составляет 90% случаев), он
StringBuilder
будет работать намного быстрее, потому что не остановится, чтобы увидеть, владеет ли он блокировкой потока.Таким образом, рекомендуется использовать
StringBuilder
(если, конечно, у вас есть несколько потоков, обращающихся к нему одновременно, что редко)String
конкатенация ( с использованием оператора + ) может быть оптимизирована компилятором для использованияStringBuilder
под ней, так что больше не о чем беспокоиться, в древние времена Java это было то, о чем все говорят, что следует избегать любой ценой, потому что каждая конкатенация создал новый объект String. Современные компиляторы больше этого не делают, но все же рекомендуется использовать их наStringBuilder
всякий случай, если вы используете «старый» компилятор.редактировать
Просто для того, кому интересно, вот что делает компилятор для этого класса:
javap -c StringConcatenation
Строки с номерами 5 - 27 предназначены для строки с именем «literal».
Строки с номерами 31-53 предназначены для строки с именем «строитель»
Разницы нет, для обеих строк выполняется одинаковый код.
источник
StringBuilder
конкатенацию для выполнения строк в правой части назначения. Любая хорошая реализация будет использовать StringBuilder за кулисами, как вы говорите. Кроме того, ваш пример"a" + "b"
будет скомпилирован в один литерал,"ab"
но если выStringBuilder
его используете, это приведет к двум ненужным вызовамappend()
."a"+"b"
но чтобы сказать, что такое конкатенация строк, я изменил ее на явный. То, что вы не говорите, это то, почему не стоит делать это. Это именно то, что делает (современный) компилятор. @ fuzzy, я согласен, особенно если вы знаете, какой будет размер последней строки (aprox).источник
synchronised
и вот почему .строка
String class
Представляет собой строку символов. Все строковые литералы в Java-программе, например"abc"
, реализованы как экземпляры этого класса.Строковые объекты неизменны, как только они созданы, мы не можем их изменить. ( Строки являются постоянными )
Если строка создается с помощью конструктора или метода , то эти строки будут храниться в динамической памяти , а также
SringConstantPool
. Но перед сохранением в пуле он вызываетintern()
метод проверки доступности объекта с тем же содержимым в пуле, используя метод equals. Если в пуле имеется String-copy, возвращается ссылка. В противном случае объект String добавляется в пул и возвращает ссылку.+
) и для преобразования других объектов в строки. Конкатенация строк реализуется через класс StringBuilder (или StringBuffer) и его метод добавления.Строковые литералы хранятся в
StringConstantPool
.StringBuilder и StringBuffer являются изменяемой последовательностью символов. Это означает, что можно изменить значение этих объектов. StringBuffer имеет те же методы, что и StringBuilder, но каждый метод в StringBuffer синхронизирован, поэтому он безопасен для потоков.
Данные StringBuffer и StringBuilder могут быть созданы только с использованием оператора new. Таким образом, они сохраняются в памяти кучи.
Экземпляры StringBuilder не безопасны для использования несколькими потоками. Если такая синхронизация требуется, то рекомендуется использовать StringBuffer.
StringBuffer и StringBuilder оказывают специальные методы , такие как.,
replace(int start, int end, String str)
Иreverse()
.Когда использовать какой.
Если вы не собираетесь менять значение каждый раз, то лучше использовать
String Class
. Как часть Обобщений, если вы хотите СортироватьComparable<T>
или сравнить значения, тогда переходите кString Class
.Если вы собираетесь каждый раз изменять значение, используйте StringBuilder, который работает быстрее, чем StringBuffer. Если несколько потоков изменяют значение, переходите к StringBuffer.
источник
Кроме того,
StringBuffer
потокобезопасен, чтоStringBuilder
не так.Так что в ситуации реального времени, когда разные потоки обращаются к нему,
StringBuilder
может иметь неопределенный результат.источник
Обратите внимание, что если вы используете Java 5 или новее, вы должны использовать
StringBuilder
вместоStringBuffer
. Из документации API:На практике вы почти никогда не будете использовать это из нескольких потоков одновременно, поэтому синхронизация
StringBuffer
почти всегда не требует ненужных затрат.источник
Лично я не думаю, что есть реальная польза для этого
StringBuffer
. Когда я захочу общаться между несколькими потоками, манипулируя последовательностью символов? Звучит совсем не полезно, но, может быть, мне еще предстоит увидеть свет :)источник
Разница между String и двумя другими классами заключается в том, что String является неизменным, а два других являются изменяемыми классами.
Но почему у нас есть два класса для одной цели?
Причина в том, что
StringBuffer
является потокобезопасным иStringBuilder
не является.StringBuilder
Это новый класс,StringBuffer Api
который был введенJDK5
и всегда рекомендуется, если вы работаете в однопоточной среде, так какFaster
Для получения полной информации вы можете прочитать http://www.codingeek.com/java/stringbuilder-and-stringbuffer-a-way-to-create-mutable-strings-in-java/
источник
В Java String является неизменным. Будучи неизменными, мы имеем в виду, что после создания строки мы не можем изменить ее значение. StringBuffer является изменяемым. После создания объекта StringBuffer мы просто добавляем содержимое к значению объекта, а не создаем новый объект. StringBuilder похож на StringBuffer, но он не является потокобезопасным. Методы StingBuilder не синхронизированы, но по сравнению с другими строками Stringbuilder работает быстрее всего. Вы можете узнать разницу между String, StringBuilder и StringBuffer , реализовав их.
источник