Сложение строк: concat() против оператора "+"
Вопрос на StackOverflow:
Я изучаю использование операторов в Java и хотел бы понять, работают ли операции с concatenation строк одинаково в случае использования оператора +=
и метода concat()
.
У меня есть два примера:
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);
}
}
Я бы также хотел знать, можно ли декомпилировать оператор +
, чтобы увидеть, как он работает.
Может ли кто-нибудь объяснить, есть ли разница между этими подходами и как можно проанализировать внутреннюю реализацию оператора +
? Спасибо!
5 ответ(ов)
Я провел аналогичный тест, как и @marcio, но с использованием следующего цикла:
String c = a;
for (long i = 0; i < 100000L; i++) {
c = c.concat(b); // чтобы javac не мог пропустить цикл
// вместо этого можно использовать c += b
}
Для полной уверенности я также добавил StringBuilder.append()
. Каждый тест выполнялся 10 раз с 100 тысячами итераций для каждого запуска. Вот результаты:
StringBuilder
абсолютно выигрывает. В большинстве запусков время замера было 0, а самый долгий занял 16 мс.a += b
занимает около 40000 мс (40 с) на каждый запуск.concat
требует всего 10000 мс (10 с) на запуск.
Я еще не декомпилировал класс, чтобы посмотреть внутренности, или запускал его через профайлер, но подозреваю, что a += b
тратит значительное время на создание новых объектов StringBuilder
, а затем преобразует их обратно в String
.
На данный момент, судя по вашим замерам, можно констатировать, что производительность операции конкатенации строк в Java существенно изменилась с тех пор, как в 2008 году давались рекомендации по использованию метода concat
. В моих последних тестах, проведенных с использованием JMH на Java 8, оператор +
оказался примерно в два раза быстрее, чем concat
.
Вот результаты моего бенчмарка:
Benchmark Mode Cnt Score Error Units
StringConcatenation.concat_2 thrpt 50 24908871.258 ± 1011269.986 ops/s
StringConcatenation.concat_3 thrpt 50 14228193.918 ± 466892.616 ops/s
StringConcatenation.concat_4 thrpt 50 9845069.776 ± 350532.591 ops/s
StringConcatenation.plus_2 thrpt 50 38999662.292 ± 8107397.316 ops/s
StringConcatenation.plus_3 thrpt 50 34985722.222 ± 5442660.250 ops/s
StringConcatenation.plus_4 thrpt 50 31910376.337 ± 2861001.162 ops/s
StringConcatenation.stringbuilder_2 thrpt 50 40472888.230 ± 9011210.632 ops/s
StringConcatenation.stringbuilder_3 thrpt 50 33902151.616 ± 5449026.680 ops/s
StringConcatenation.stringbuilder_4 thrpt 50 29220479.267 ± 3435315.681 ops/s
Как видно из данных, использование оператора +
для конкатенации строк показывает значительно большую производительность по сравнению с методом concat
. Это может быть связано с улучшениями в оптимизации компилятора и самого языка Java. Следовательно, для современных приложений в Java 8 и позже рекомендуется использовать оператор +
, особенно в контексте небольших операций конкатенации.
Если вам нужно объединять большое количество строк, и вы хотите добиться максимальной производительности, лучше всего использовать StringBuilder
. Однако в большинстве случаев, как показывают результаты, +
также предлагает отличное соотношение производительности и простоты использования.
Ваше тестирование кажется интересным и показывает некоторые нюансы работы с конкатенацией строк в Java. Давайте разберемся с вашим вопросом.
Вы привели пример кода, в котором сравнили время выполнения двух способов объединения строк: с использованием String.concat()
и оператора +
. Результаты оказались неожиданными, так как concat()
выполняется быстрее.
Давайте рассмотрим несколько моментов:
Операции со строками: В Java строки неизменяемы (immutable), и каждый раз, когда вы выполняете операцию конкатенации, создается новая строка. Оператор
+
в Java может вызыватьStringBuilder
под капотом для оптимизации, особенно когда он используется в контексте, где известен размер строки заранее (например, вStringBuilder
).Оптимизация компилятора: Java-компилятор (JIT) не всегда может оптимизировать конкатенации строк, используя
+
, особенно если вы выполняете много операций в цикле, как в вашем случае. Комpилятор может не распознать, что в каждом шаге создается одинаковая строка, что может привести к дополнительным накладным расходам.Переполнение строк: В случае с
String.concat()
каждый раз создается новая строка, так же как и дляa + b
, но методconcat()
может быть оптимизирован по сравнению с использованием+
, чтобы избежать дополнительных накладных расходов, связанных с управлением памятью и вызовами методов.Изменение кода: Для более эффективной конкатенации в таких ситуациях рекомендуется использовать
StringBuilder
илиStringBuffer
, особенно когда нужно объединить много строк. Например:StringBuilder sb = new StringBuilder(); for (int i = 0; i < 10000000; i++) { sb.append(a).append(b); } String result = sb.toString();
Таким образом, результаты ваших измерений могут быть вызваны различиями в оптимизации между различными подходами. Если вы хотите максимально увеличить производительность, использование StringBuilder
будет более предпочтительным решением.
Пожалуйста, проводите тесты и делитесь результатами — это может быть полезным для понимания нюансов работы с строками в Java!
Существует два основных отличия между оператором + и методом concat
.
Если вы используете метод concat, то можете объединять только строки. В отличие от этого, при использовании оператора + вы можете объединять строку с любым другим типом данных.
Например:
String s = 10 + "Hello";
В этом случае результат будет 10Hello.
String s = "I"; String s1 = s.concat("am").concat("good").concat("boy"); System.out.println(s1);
В этом случае необходимо предоставить две строки.
Второе и главное отличие между + и concat заключается в следующем:
Случай 1: Предположим, я объединяю одни и те же строки с помощью метода concat следующим образом:
String s = "I"; String s1 = s.concat("am").concat("good").concat("boy"); System.out.println(s1);
В этом случае общее количество объектов, созданных в пуле, составит 7:
I am good boy Iam Iamgood Iamgoodboy
Случай 2:
Теперь я собираюсь объединить те же строки с помощью оператора +:
String s = "I" + "am" + "good" + "boy"; System.out.println(s);
В этом случае общее количество созданных объектов составит всего 5.
На самом деле, когда мы объединяем строки через оператор +, используется класс StringBuffer для выполнения этой задачи таким образом:
StringBuffer sb = new StringBuffer("I"); sb.append("am"); sb.append("good"); sb.append("boy"); System.out.println(sb);
Таким образом, будет создано только пять объектов.
Итак, ребята, это основные отличия между + и методом concat. Наслаждайтесь! 😃
Оператор + может использоваться для объединения строки с другой строкой, символом, целым числом, числом с плавающей запятой (double) или float. В этом случае он просто преобразует второе значение в его строковое представление перед конкатенацией.
Оператор конкатенации (concat) может применяться только к строкам. Он проверяет совместимость типов данных и выдает ошибку, если они не совпадают.
Кроме этого, приведённый вами код выполняет те же самые действия.
StringBuilder против конкатенации строк в toString() в Java
Как преобразовать строку в int в Java?
Преобразование 'ArrayList<String>' в 'String[]' в Java
Как сгенерировать случайную алфавитно-цифровую строку
Как преобразовать строку Java в byte[]?