Когда мы должны изменить String на Stringbuilder?

В приложении String - это часто используемый тип данных. Что мы знаем, так это то, что мутация строки использует много памяти. Так что мы можем использовать StringBuilder / StringBuffer.

Но в какой момент мы должны перейти на StringBuilder?
И что нам делать, когда мы должны разделить это или заменить символы там?

например:

 //original:
 String[] split = string.split("?");  
 //better? :  
 String[] split = stringBuilder.toString().split("?);

или же

 //original:
 String replacedString = string.replace("l","st");  
 //better? :  
 String replacedString = stringBuilder.toString().replace("l","st");  
 //or  
 StringBuilder replacedStringBuilder = new StringBuilder(stringBuilder.toString().replace("l","st);

5 ответов

Решение

Что мы знаем, так это то, что мутация строки использует много памяти.

Это неверно. Строки не могут быть изменены. Они неизменны.

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

Так что мы можем использовать StringBuilder/StringBuffer.

Использование StringBuilder поможет в некоторых случаях:

  String res = "";
  for (String s : ...) {
      res = res + s;
  }

(Если цикл повторяется много раз, то может оказаться целесообразным оптимизировать вышеприведенное для использования StringBuilder.)

Но при других обстоятельствах это пустая трата времени:

  String res = s1 + s2 + s3 + s4 + s5;

(Оптимизировать приведенное выше для использования StringBuilder - пустая трата времени, поскольку компилятор Java автоматически преобразует выражение в код, который создает и использует StringBuilder.)

Вы должны когда-либо использовать StringBuffer вместо StringBuilder только тогда, когда строка должна быть доступна и / или обновлена ​​более чем одним потоком; то есть когда это должно быть потокобезопасным.

Но в какой момент мы должны перейти на StringBuilder?

Простой ответ - сделать это только тогда, когда профилировщик скажет вам, что у вас проблемы с производительностью при обработке / обработке строк.

Вообще говоря, StringBuilders используются для построения строк, а не в качестве основного представления строк.

И что мы должны делать, когда мы должны разделить это или заменить символы там?

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

В ваших примерах нет никаких преимуществ в использовании StringBuilder, так как вы используете toString способ создать неизменный String из вашего StringBuilder,

Вы должны только скопировать содержимое StringBuilder в String после того, как вы закончите добавление (или изменение каким-либо другим способом).

Проблема с Java StringBuilder является то, что ему не хватает некоторых методов, которые вы получаете при использовании простой строки (проверьте этот поток, например: Как реализовать StringBuilder.replace (String, String)).

Что мы знаем, так это то, что строка использует много памяти.

На самом деле, если быть точным, String использует меньше памяти, чем StringBuilder с эквивалентным содержанием. StringBuilder Класс имеет некоторые дополнительные постоянные издержки и обычно имеет предварительно выделенный буфер для хранения большего количества данных, чем необходимо в любой данный момент (чтобы уменьшить выделения). Вопрос с StringСуть в том, что они неизменны, что означает, что Java должна создавать новый экземпляр всякий раз, когда вам нужно изменить его содержимое.

Заключить, StringBuilder не предназначен для операций, которые вы упомянули (разделить и заменить), и в любом случае он не даст намного лучшей производительности. split метод не может извлечь выгоду из StringBuilderизменчивость, так как он создает массив неизменяемых строк в любом случае. Методом замены по-прежнему необходимо перебирать всю строку и выполнять многократное копирование, если замещаемая строка не соответствует размеру искомой.

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

В этой статье сравнивается производительность нескольких StringBuilder а также String методы (хотя я бы взял часть конкатенации с резервом, потому что она не упоминает динамическое добавление строки вообще и концентрируется на одном Join только операция).

Если вы часто изменяете строку, перейдите с StringBuilder, В противном случае, если это так или иначе является неизменным, пойти с String,

Чтобы ответить на ваш вопрос о том, как заменить символы, проверьте это: http://download.oracle.com/javase/tutorial/java/data/buffers.html. Операции StringBuilder - это то, что вы хотите.

Вот еще одна хорошая статья о StringBuilder: http://www.yoda.arachsys.com/csharp/stringbuilder.html

Если вам нужно много операций по изменению вашего Stringтогда вы можете пойти на StringBuilder, Пойти на StringBuffer если вы находитесь в многопоточном приложении.

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

Если вы измерили (например, с jmap -histo:live) что классы [C а также java.lang.String занять большую часть памяти в куче, только тогда вы должны думать дальше в этом направлении.

Может быть, есть несколько строк с одинаковым значением. Тогда, так как Strings являются неизменными, вы могли бы интернировать дубликаты строк. Не использовать String.intern для него, так как он имеет плохие характеристики производительности, но Google Guava Interner,

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