Когда мы должны использовать + для конкатенации строк, когда предпочтительнее StringBuilder и когда подходит для использования concat.
Я слышал, что StringBuilder предпочтительнее для конкатенации внутри циклов. Почему это так?
Спасибо.
Когда мы должны использовать + для конкатенации строк, когда предпочтительнее StringBuilder и когда подходит для использования concat.
Я слышал, что StringBuilder предпочтительнее для конкатенации внутри циклов. Почему это так?
Спасибо.
Я обычно использую StringBuilder
в кодах, где производительность является проблемой. Повторная конкатенация строк внутри цикла часто является хорошим кандидатом.
Причиной предпочтения StringBuilder
является то, что оба +
и concat
создают новый объект каждый раз, когда вы их вызываете (если аргумент правой стороны не пуст). Это может быстро добавить к большому количеству объектов, почти все из которых совершенно не нужны.
Как указывали другие, когда вы используете +
несколько раз в рамках одного и того же оператора, компилятор может часто оптимизировать это для вас. Однако, по моему опыту, этот аргумент не применяется, когда конкатенации происходят в отдельных утверждениях. Это, конечно, не помогает с циклами.
Сказав все это, я считаю, что главный приоритет должен заключаться в написании четкого кода. Для Java доступны некоторые отличные инструменты для профилирования (я использую YourKit), что позволяет легко выявлять узкие места производительности и оптимизировать только те биты, в которых это важно.
P.S. Мне никогда не приходилось использовать concat
.
Современный компилятор Java преобразует ваши + операции в приложение StringBuilder. Я хочу сказать, если вы выполните str = str1 + str2 + str3
, тогда компилятор сгенерирует следующий код:
StringBuilder sb = new StringBuilder();
str = sb.append(str1).append(str2).append(str3).toString();
Вы можете декомпилировать код с помощью DJ или Cavaj, чтобы подтвердить это:) Итак, теперь это более важный выбор, чем преимущество в производительности для использования + или StringBuilder:)
Однако, учитывая ситуацию, когда компилятор не делает этого для вашего (если вы используете какой-либо частный Java SDK для этого, это может произойти), то, безусловно, StringBuilder - это путь, по которому вы избегаете большого количества ненужных String
объектов.
String
String
является неизменным: вы не можете изменить объектString
, но можете его заменить, создав новый экземпляр. Создание нового экземпляра довольно дорого.//Inefficient version using immutable String String output = "Some text"; int count = 100; for (int i = 0; i < count; i++) { output += i; } return output;
В приведенном выше коде будет создано 99 новых объектов
String
, из которых 98 будет немедленно выброшено. Создание новых объектов неэффективно.
StringBuffer
/StringBuilder
StringBuffer
изменен: используйтеStringBuffer
илиStringBuilder
, если вы хотите изменить содержимое.StringBuilder
был добавлен в Java 5 и во всех отношениях идентиченStringBuffer
, за исключением того, что он не синхронизирован, что делает его немного быстрее за счет того, что он не является потокобезопасным.//More efficient version using mutable StringBuffer StringBuffer output = new StringBuffer(110); output.append("Some text"); for (int i = 0; i < count; i++) { output.append(i); } return output.toString();
В приведенном выше коде создаются только два новых объекта:
StringBuffer
и окончательныйString
, который возвращается.StringBuffer
расширяется по мере необходимости, что дорого стоит, поэтому было бы лучше инициализироватьStringBuffer
с правильным размером с самого начала, как показано.
Если все конкатенированные элементы являются константами (пример: "these" + "are" + "constants"
), то я бы предпочел +, потому что компилятор будет встраивать конкатенацию для вас. В противном случае использование StringBuilder является наиболее эффективным способом.
Если вы используете + с неконстантами, компилятор будет внутренне использовать StringBuilder, но отладка становится адом, потому что используемый код больше не идентичен вашему исходному коду.
Моя рекомендация будет следующей:
+
: Используйте при объединении 2 или 3 строк просто для того, чтобы ваш код был коротким и читаемым.StringBuilder
: Используйте при создании сложного строкового вывода или в том, что касается производительности.String.format
: Вы не упомянули об этом в своем вопросе, но это мой предпочтительный метод для создания строк, поскольку он сохраняет код наиболее читаемым/сжатым, на мой взгляд, и особенно полезен для операторов журнала.concat
: Я не думаю, что у меня когда-либо были причины использовать это.Используйте StringBuilder
, если вы много манипулируете. Обычно это довольно хороший признак.
Причиной этого является то, что при использовании обычной конкатенации получается много промежуточного объекта String
, который не может быть легко "расширен" (т.е. каждая операция конкатенации создает копию, требующую памяти и времени процессора). A StringBuilder
, с другой стороны, нужно лишь скопировать данные в некоторых случаях (вставка чего-то посередине или изменение размера, потому что результат становится большим), поэтому он сохраняет эти операции копирования.
Использование concat()
не имеет реальной пользы от использования +
(он может быть немного быстрее для одного +
, но как только вы сделаете a.concat(b).concat(c)
, он будет на самом деле медленнее, чем a + b + c
).
Коэффициент усиления от компилятора применяется к конкатенационным константам. Остальные используются на самом деле медленнее, чем напрямую с помощью StringBuilder.
Нет проблем с использованием "+", например. для создания сообщения об исключении, потому что это происходит нечасто, и приложение si уже каким-то образом ввернулось в данный момент. Избегайте использования "+" в циклах.
Для создания значимых сообщений или других параметризованных строк (выражения Xpath, например,) используйте String.format - это гораздо лучше читаемый.
Используйте + для одиночных операторов и StringBuilder для нескольких операторов/циклов.
Я предлагаю использовать concat для двух конкатенаций строк и StringBuilder в противном случае, см. мои объяснения для оператора конкатенации (+) vs concat()