Предполагая строку a и b:
a += b
a = a.concat(b)
Под капотом они одно и то же?
Здесь concat декомпилирован как ссылка. Я хотел бы иметь возможность декомпилировать +
оператора, чтобы увидеть, что это делает.
public String concat(String s) {
int i = s.length();
if (i == 0) {
return this;
}
else {
char ac[] = new char[count + i];
getChars(0, count, ac, 0);
s.getChars(0, i, ac, count);
return new String(0, count + i, ac);
}
}
java
string
concatenation
shsteimer
источник
источник
+
можно декомпилировать.StringBuffer
илиStringBuilder
- (поток небезопасен, поэтому быстрее, вместо этогоОтветы:
Нет не совсем
Во-первых, есть небольшая разница в семантике. Если
a
естьnull
, тоa.concat(b)
бросает,NullPointerException
ноa+=b
будет обрабатывать исходное значение,a
как если бы это былоnull
. Кроме того,concat()
метод принимает толькоString
значения, в то время как+
оператор автоматически преобразует аргумент в строку (используяtoString()
метод для объектов). Таким образом,concat()
метод более строг в том, что он принимает.Чтобы заглянуть под капот, напишите простой класс с
a += b;
Теперь разберите с
javap -c
(входит в Sun JDK). Вы должны увидеть список, включающий:Итак,
a += b
является эквивалентомconcat
Метод должен быть быстрее. Однако при большем количестве строкStringBuilder
метод побеждает, по крайней мере, с точки зрения производительности.Исходный код
String
иStringBuilder
(и его закрытый для пакета базовый класс) доступен в src.zip Sun JDK. Вы можете видеть, что вы создаете массив символов (изменяя размер по мере необходимости), а затем выбрасываете его, когда создаете финалString
. На практике распределение памяти происходит на удивление быстро.Обновление: как отмечает Павел Адамски, производительность изменилась в более позднем HotSpot.
javac
все еще производит точно такой же код, но компилятор байт-кода обманывает. Простое тестирование полностью терпит неудачу, потому что весь объем кода отбрасывается. СуммированиеSystem.identityHashCode
(неString.hashCode
) показывает, чтоStringBuffer
код имеет небольшое преимущество. Возможны изменения при выходе следующего обновления или при использовании другой JVM. От @lukaseder , список встроенных функций HotSpot JVM .источник
javap -c
в скомпилированном классе, который его использует. (О, как в ответе. Вам просто нужно интерпретировать разборку байт-кода, что не должно быть так сложно.)StringBuilder
даже при соединении двух строк? ЕслиString
включены статические методы для конкатенации до четырех строк или всех строк вString[]
коде, можно добавить до четырех строк с двумя выделениями объектов (результатString
и его поддержкаchar[]
, ни один с избыточностью), и любое количество строк с тремя выделениями (String[]
, результатString
, а подложкаchar[]
, только первый является излишним). Как это, используяStringBuilder
волю в лучшем случае потребуется четыре распределения, и потребуют копирования каждого персонажа дважды.Нияз прав, но также стоит отметить, что специальный оператор + может быть преобразован во что-то более эффективное компилятором Java. В Java есть класс StringBuilder, который представляет не поточнобезопасную изменяемую строку. При выполнении связки строк String, компилятор Java молча преобразует
в
что для больших струн значительно эффективнее. Насколько я знаю, этого не происходит при использовании метода concat.
Однако метод concat более эффективен при объединении пустой строки в существующую строку. В этом случае JVM не нужно создавать новый объект String, и он может просто вернуть существующий. См. Документацию concat, чтобы подтвердить это.
Так что, если вы очень обеспокоены эффективностью, тогда вам следует использовать метод concat при конкатенации, возможно, пустых строк, и использовать + в противном случае. Однако разница в производительности должна быть незначительной, и вам, вероятно, не стоит беспокоиться об этом.
источник
String
- как вы говорите,concat
есть одно исключение, когда вы конкатанируете пустоеString
.Я запустил такой же тест как @marcio, но вместо этого использовал следующий цикл:
Просто для хорошей меры, я также добавил
StringBuilder.append()
. Каждый тест был выполнен 10 раз, с 100 000 повторений для каждого запуска. Вот результаты:StringBuilder
выигрывает руки вниз Результат времени был равен 0 для большинства запусков, а самый длинный - 16 мс.a += b
занимает около 40000 мс (40 с) для каждого запуска.concat
требуется только 10000 мс (10 с) за цикл.Я еще не декомпилировал класс, чтобы увидеть внутреннее устройство или запустить его через профилировщик, но я подозреваю, что
a += b
большую часть времени проводит, создавая новые объектыStringBuilder
и затем преобразовывая их обратноString
.источник
+
используется для двух строк, есть ли случаи, когда использованиеStringBuilder
лучше, чем было быString.valueOf(s1).concat(s2)
? Любая идея, почему компиляторы не будут использовать последний [или иначе пропуститьvalueOf
вызов в случаях, когдаs1
известно, что он не равен нулю]?Большинство ответов здесь с 2008 года. Похоже, что со временем все изменилось. Мои последние тесты, сделанные с помощью JMH, показывают, что в Java 8
+
примерно в два раза быстрее, чемconcat
.Мой тест:
Результаты:
источник
String
никогда не включал статическую функцию для формирования строки путем объединения элементов aString[]
. Использование+
для объединения 8 строк с использованием такой функции потребовало бы конструирования и последующего отказаString[8]
, но это был бы единственный объект, который нужно было бы создать оставленным, в то время как использование объектаStringBuilder
потребовало бы создания и отказа отStringBuilder
экземпляра и по крайней мере одногоchar[]
резервного хранилища.String.join()
методы были добавлены в Java 8 как быстрые синтаксические обёртки вокругjava.util.StringJoiner
класса.+
для использования таких функций?+
сожалению, остальная часть вашего предложения (рефакторинг для его использования) потребует большего, чем то, что разработчики Java готовы изменить.Том прав в описании того, что делает оператор +. Он создает временный
StringBuilder
, добавляет части и заканчиваетсяtoString()
.Тем не менее, все ответы до сих пор игнорируют эффекты оптимизации во время выполнения HotSpot. В частности, эти временные операции распознаются как общий шаблон и заменяются более эффективным машинным кодом во время выполнения.
@marcio: вы создали микро-тест ; в современных JVM это недопустимый способ профилировать код.
Причиной оптимизации во время выполнения является то, что многие из этих различий в коде - даже в том числе создание объектов - после запуска HotSpot полностью различаются. Единственный способ узнать наверняка - это профилировать ваш код на месте .
Наконец, все эти методы на самом деле невероятно быстрые. Это может быть случай преждевременной оптимизации. Если у вас есть код, который объединяет строки много, способ получить максимальную скорость, вероятно, не имеет ничего общего с тем, какие операторы вы выбираете, а вместо этого алгоритм, который вы используете!
источник
Как насчет простого тестирования? Использовал код ниже:
"a + b"
Версия выполнена в 2500ms .a.concat(b)
Выполнен в 1200ms .Проверено несколько раз.
concat()
Исполнение версии взяла половину времени в среднем.Этот результат меня удивил, потому что
concat()
метод всегда создает новую строку (он возвращает "new String(result)
". Хорошо известно, что:Почему компилятор не был способен оптимизировать создание строки в коде "a + b", зная, что это всегда приводит к одной и той же строке? Это могло бы избежать создания новой строки. Если вы не верите утверждению выше, проверьте себя.
источник
В принципе, есть два важных различия между + и
concat
методом.Если вы используете метод concat, то вы сможете конкатенировать только строки, а в случае оператора + вы можете также конкатенировать строку с любым типом данных.
Например:
В этом случае вывод должен быть Hello .
В приведенном выше случае вы должны предоставить две строки обязательно.
Второе и основное отличие между + и concat заключается в том, что:
Случай 1: Предположим, я конкатирую одни и те же строки с помощью оператора concat таким образом
В этом случае общее количество объектов, созданных в пуле, равно 7:
Случай 2:
Теперь я собираюсь объединить те же строки с помощью оператора +
В приведенном выше случае общее количество созданных объектов составляет всего 5.
На самом деле, когда мы объединяем строки с помощью оператора +, он поддерживает класс StringBuffer для выполнения той же задачи, как показано ниже:
Таким образом, он будет создавать только пять объектов.
Так что, ребята, это основные различия между + и методом concat . Наслаждаться :)
источник
String s="I"+"am"+"good"+"boy"; String s2 = "go".concat("od"); System.out.println(s2 == s2.intern());
печатаетtrue
, что означает, что"good"
не было в пуле строк до вызоваintern()
Для полноты картины я хотел бы добавить, что определение оператора '+' можно найти в JLS SE8 15.18.1 :
О реализации JLS говорит следующее:
Таким образом, исходя из того, что «компилятор Java может использовать класс StringBuffer или подобный метод для сокращения», разные компиляторы могут создавать разные байт-коды.
источник
Оператор + может работать между строкой и значением типа данных string, char, integer, double или float. Он просто преобразует значение в свое строковое представление перед объединением.
Оператор concat может выполняться только со строками. Он проверяет совместимость типов данных и выдает ошибку, если они не совпадают.
Кроме того, код, который вы предоставили, делает то же самое.
источник
Я так не думаю.
a.concat(b)
реализован в String, и я думаю, что реализация не сильно изменилась с ранних Java-машин. Реализация+
операции зависит от версии Java и компилятора. В настоящее время+
реализовано использование,StringBuffer
чтобы сделать операцию максимально быстрой. Возможно, в будущем это изменится. В более ранних версиях Java+
работа со строками была намного медленнее, поскольку она давала промежуточные результаты.Я предполагаю, что
+=
это реализовано с использованием+
и аналогичным образом оптимизировано.источник
При использовании + скорость уменьшается по мере увеличения длины строки, но при использовании concat скорость более стабильна, и лучшим вариантом для этого является использование класса StringBuilder, который имеет стабильную скорость.
Я думаю, вы можете понять, почему. Но самый лучший способ создания длинных строк - это использование StringBuilder () и append (), любая скорость будет недопустимой.
источник