Учитывая 2 toString()
реализации ниже, какая из них является предпочтительной:
public String toString(){
return "{a:"+ a + ", b:" + b + ", c: " + c +"}";
}
или
public String toString(){
StringBuilder sb = new StringBuilder(100);
return sb.append("{a:").append(a)
.append(", b:").append(b)
.append(", c:").append(c)
.append("}")
.toString();
}
?
Что еще более важно, учитывая, что у нас есть только 3 свойства, это может не иметь значения, но в какой момент вы бы переключились с +
concat на StringBuilder
?
java
performance
string
concatenation
stringbuilder
не секвитор
источник
источник
StringBuilder
какой размер выделять авансом, в противном случае, если ему не хватит места, придется удвоить размер, создав Новыйchar[]
массив затем скопировать данные поверх - что дорого. Вы можете обмануть, указав размер, и тогда нет необходимости в создании этого массива - поэтому, если вы считаете, что ваша строка будет длиной ~ 100 символов, вы можете установить StringBuilder на этот размер, и он никогда не будет расширяться внутри.Ответы:
Версия 1 предпочтительнее, потому что она короче, и компилятор фактически превратит ее в версию 2 - без разницы в производительности.
В тот момент, когда вы объединяете в цикле - обычно, когда компилятор не может заменить
StringBuilder
его сам.источник
To increase the performance of repeated string concatenation, a Java compiler _may_ use the StringBuffer class or a similar technique to reduce the number of intermediate String objects that are created by evaluation of an expression.
Ключевое слово там может быть . Учитывая, что это официально необязательно (хотя, скорее всего, реализовано), не должны ли мы защитить себя?Ключ в том, пишете ли вы одну конкатенацию в одном месте или накапливаете ее с течением времени.
Для приведенного вами примера нет смысла явно использовать StringBuilder. (Посмотрите скомпилированный код для вашего первого случая.)
Но если вы строите строку, например, внутри цикла, используйте StringBuilder.
Чтобы уточнить, если предположить, что огромный массив содержит тысячи строк, напишите следующий код:
очень трата времени и памяти по сравнению с:
источник
result += s;
(в первом примере)"{a:"+ a + ", b:" + b + ", c: " + c +"}";
Я предпочитаю:
... потому что он короткий и читаемый.
Я бы не стал оптимизировать это для скорости, если вы не используете его внутри цикла с очень большим количеством повторений и не измерили разницу в производительности.
Я согласен, что если вам нужно вывести много параметров, эта форма может запутаться (как говорится в одном из комментариев). В этом случае я бы переключился на более читаемую форму (возможно, используя ToStringBuilder из apache-commons - взятый из ответа matt b) и снова проигнорировал бы производительность.
источник
null
В большинстве случаев вы не увидите реальной разницы между этими двумя подходами, но легко построить худший сценарий, подобный этому:
Выход:
Проблема в том, что добавление + = к строке восстанавливает новую строку, поэтому она стоит что-то линейное по отношению к длине ваших строк (сумма обоих).
Итак - на ваш вопрос:
Второй подход был бы быстрее, но он менее читабелен и сложнее в обслуживании. Как я уже сказал, в вашем конкретном случае вы, вероятно, не увидите разницу.
источник
+=
, оригинальный пример представлял собой последовательность+
, которую компилятор преобразует в одинstring.concat
вызов. Ваши результаты не применяются.Я также столкнулся с моим боссом по поводу того, использовать ли append или +. Поскольку они используют Append (я до сих пор не могу понять, как они говорят каждый раз, когда создается новый объект). Поэтому я подумал сделать несколько R & D. Хотя мне нравится объяснение Майкла Боргвардта, но я просто хотел показать объяснение, если кому-то действительно нужно будет знать в будущем.
и разборка вышеупомянутого класса выходит как
Из приведенных выше двух кодов видно, что Майкл прав. В каждом случае создается только один объект SB.
источник
Начиная с Java 1.5, простая конкатенация в одну строку с "+" и StringBuilder.append () генерируют точно такой же байт-код.
Поэтому для удобства чтения кода используйте «+».
2 исключения:
источник
Используя последнюю версию Java (1.8), disassembly (
javap -c
) показывает оптимизацию, представленную компилятором.+
такжеsb.append()
будет генерировать очень похожий код. Тем не менее, стоит проверить поведение, если мы используем+
цикл for.Добавление строк с помощью + в цикле for
Ява:
ByteCode :(
for
отрывок цикла)Добавление строк с использованием stringbuilder.append
Ява:
ByteCdoe :(
for
отрывок цикла)Есть небольшая явная разница . В первом случае, где
+
был использован,StringBuilder
для каждой итерации цикла создается новый, а сгенерированный результат сохраняется с помощьюtoString()
вызова (с 29 по 41). Таким образом, вы генерируете промежуточные строки, которые вам действительно не нужны при использовании+
оператора вfor
цикле.источник
В Java 9 версия 1 должна быть быстрее, потому что она преобразуется в
invokedynamic
вызов. Более подробную информацию можно найти в JEP-280 :источник
Из соображений производительности использование
+=
(String
сцепления) не рекомендуется. Причина в том, что JavaString
является неизменным, каждый раз, когда выполняется новая конкатенация, создается новаяString
(новая имеет отпечаток, отличный от старого, уже находящегося в пуле строк). ). Создание новых строк оказывает давление на ГХ и замедляет программу: создание объектов стоит дорого.Приведенный ниже код должен сделать его более практичным и понятным одновременно.
Результаты пробега сообщаются ниже.
Не учитывая результаты для 1 конкатенации (JIT еще не выполнил свою работу), даже для 10 конкатенаций снижение производительности является значимым; для тысяч конкатенаций разница огромна.
Уроки, извлеченные из этого очень быстрого эксперимента (легко воспроизводимого с помощью приведенного выше кода): никогда не используйте
+=
для объединения строк вместе, даже в очень простых случаях, когда требуется несколько объединений (как уже говорилось, создание новых строк в любом случае стоит дорого и оказывает давление на ГХ).источник
Смотрите пример ниже:
Вывод:
По мере увеличения длины строки время конкатенации увеличивается.
Вот где
StringBuilder
это определенно необходимо.Как видите, конкатенация:
UUID.randomUUID()+"---"
действительно не влияет на время.PS: я не думаю, что когда использовать StringBuilder в Java, это действительно дубликат этого.
Этот вопрос говорит о
toString()
что в большинстве случаев не выполняет конкатенации огромных строк.2019 Обновление
С тех
java8
пор все немного изменилось. Кажется, что сейчас (java13) время конкатенации+=
практически такое же, какstr.concat()
. ОднакоStringBuilder
время объединения остается неизменным . (Оригинальный пост выше был немного отредактирован, чтобы добавить более подробный вывод)Стоит отметить, что
bytecode:8/java.version:13
комбинация имеет хороший выигрыш в производительности по сравнению сbytecode:8/java.version:8
источник
java13
которые теперь отличаются. Но я думаю, что главный вывод остается прежним.Apache Commons-Lang имеет класс ToStringBuilder, который очень прост в использовании. Он отлично справляется как с логикой добавления, так и с форматированием того, как вы хотите, чтобы ваша строка была похожа.
Вернет вывод, который выглядит как
com.blah.YourClass@abc1321f[a=whatever, b=foo]
.Или в более сжатой форме, используя цепочку:
Или, если вы хотите использовать отражение, чтобы включить каждое поле класса:
Вы также можете настроить стиль ToString, если хотите.
источник
Сделайте метод toString настолько читаемым, насколько это возможно!
Единственное исключение для этого в моей книге, если вы можете доказать мне, что он потребляет значительные ресурсы :) (Да, это означает профилирование)
Также обратите внимание, что компилятор Java 5 генерирует более быстрый код, чем рукописный подход «StringBuffer», используемый в более ранних версиях Java. Если вы используете «+», это и будущие улучшения будут бесплатными.
источник
Кажется, есть некоторые споры о том, нужно ли использовать StringBuilder с текущими компиляторами. Так что я думал, что я дам свои 2 цента опыта.
У меня есть
JDBC
результирующий набор из 10 тыс. Записей (да, мне нужно, чтобы все они были в одной партии). Использование оператора + занимает около 5 минут на моей машине сJava 1.8
. ИспользованиеstringBuilder.append("")
занимает меньше секунды для того же запроса.Так что разница огромна. Внутри петли
StringBuilder
гораздо быстрее.источник
С точки зрения производительности конкатенация строк с использованием «+» обходится дороже, потому что она должна создавать совершенно новую копию строки, поскольку строки неизменяемы в Java. Это играет особую роль, если конкатенация очень частая, например: внутри цикла. Вот что предлагает моя IDEA, когда я пытаюсь сделать такую вещь:
Основные правила:
Вот хороший блог Джона Скита на эту тему.
источник
Могу ли я указать, что если вы собираетесь перебирать коллекцию и использовать StringBuilder, вы можете проверить Apache Commons Lang и StringUtils.join () (в разных вариантах)?
Независимо от производительности, это избавит вас от необходимости создавать StringBuilders и циклы для того, что кажется в миллионный раз.
источник
Вот что я проверял в Java8
Использование StringBuilder
источник
Я думаю, что мы должны пойти с подходом добавления StringBuilder. Причина в том, что:
Конкатенация String каждый раз будет создавать новый строковый объект (так как String является неизменным объектом), поэтому он создаст 3 объекта.
С помощью String Builder будет создан только один объект [StringBuilder является изменяемым], и к нему добавляется следующая строка.
источник
Для таких простых строк я предпочитаю использовать
В порядке, я бы сказал, предпочтительный метод построения строки использует StringBuilder, String # concat (), а затем перегруженный оператор +. StringBuilder - это значительное увеличение производительности, когда работа с большими строками так же, как использование оператора + - это значительное снижение производительности (экспоненциально большое уменьшение при увеличении размера строки). Единственная проблема с использованием .concat () заключается в том, что он может генерировать исключения NullPointerException.
источник