Конкатенация строк: concat () против оператора "+"
Предполагается, что строки a и b:
a += b a= a.concat(b)
По сути, это одно и то же?
Вот concat, декомпилированный в качестве ссылки. Я хотел бы иметь возможность декомпилировать + оператор, а также посмотреть, что это делает.
public String concat(String s) {
inti= s.length(); if (i == 0) { returnthis; } else { char ac[] = newchar[count + i]; getChars(0, count, ac, 0); s.getChars(0, i, ac, count); returnnewString(0, count + i, ac); } }
Переведено автоматически
Ответ 1
Нет, не совсем.
Во-первых, есть небольшая разница в семантике. Если a есть null, то a.concat(b) выдает NullPointerException но a+=b будет обрабатывать исходное значение a как если бы оно было null. Кроме того, concat() метод принимает только String значения, в то время как + оператор автоматически преобразует аргумент в строку (используя toString() метод для объектов). Таким образом, concat() метод более строгий в том, что он принимает.
Чтобы заглянуть под капот, напишите простой класс с a += b;
publicclassConcat { String cat(String a, String b) { a += b; return a; } }
Теперь разбираем с помощью javap -c (входит в Sun JDK). Вы должны увидеть список, включающий:
a = newStringBuilder() .append(a) .append(b) .toString();
concat Метод должен быть быстрее. Однако с большим количеством строк StringBuilder метод выигрывает, по крайней мере, с точки зрения производительности.
Исходный код String and StringBuilder (и его пакет-частный базовый класс) доступен в src.zip из Sun JDK. Вы можете видеть, что вы создаете массив символов (изменяя размер по мере необходимости), а затем выбрасываете его при создании окончательного String. На практике выделение памяти происходит на удивление быстро.
Обновление: Как отмечает Павел Адамски, производительность изменилась в более поздней версии HotSpot. javac по-прежнему выдает точно такой же код, но компилятор байт-кода изменяет. Простое тестирование полностью завершается неудачей, потому что выбрасывается весь текст кода. Суммирование System.identityHashCode (не String.hashCode) показывает, что StringBuffer код имеет небольшое преимущество. Может быть изменено при выпуске следующего обновления или при использовании другой JVM. От @lukaseder, список встроенных функций HotSpot JVM.
Ответ 2
Нияз правильный, но также стоит отметить, что специальный оператор + может быть преобразован во что-то более эффективное компилятором Java. В Java есть класс StringBuilder, который представляет непоточностную изменяемую строку. При выполнении нескольких конкатенаций строк компилятор Java автоматически преобразует
который для больших строк значительно эффективнее. Насколько я знаю, этого не происходит при использовании метода concat.
Однако метод concat более эффективен при объединении пустой строки с существующей. В этом случае JVM не нужно создавать новый объект String и она может просто вернуть существующий. Смотрите документацию concat, чтобы подтвердить это.
Итак, если вы очень озабочены эффективностью, то вам следует использовать метод concat при объединении возможно пустых строк и использовать + в противном случае. Однако разница в производительности должна быть незначительной, и вам, вероятно, никогда не стоит беспокоиться об этом.
Ответ 3
Я выполнил аналогичный тест, что и @marcio, но вместо него использовал следующий цикл:
Stringc= a; for (longi=0; i < 100000L; i++) { c = c.concat(b); // make sure javac cannot skip the loop // using c += b for the alternative }
На всякий случай я также добавил StringBuilder.append(). Каждый тест запускался 10 раз, по 100 тыс. повторений на каждый запуск. Вот результаты:
StringBuilder выигрывает без потерь. Результат по времени на часах был равен 0 для большинства запусков, а самый длительный занял 16 мс.
a += b занимает около 40000мс (40 секунд) для каждого запуска.
concat требуется всего 10000 мс (10 с) за запуск.
Я еще не декомпилировал класс, чтобы увидеть внутренние компоненты, или не запускал его через profiler, но я подозреваю, что a += b тратит большую часть времени на создание новых объектов из StringBuilder, а затем преобразует их обратно в String.
Ответ 4
Большинство ответов здесь относятся к 2008 году. Похоже, что со временем все изменилось. Мои последние тесты, сделанные с помощью JMH, показывают, что на Java 8 + примерно в два раза быстрее, чем concat.
Мой бенчмарк:
@Warmup(iterations = 5, time = 200, timeUnit = TimeUnit.MILLISECONDS) @Measurement(iterations = 5, time = 200, timeUnit = TimeUnit.MILLISECONDS) publicclassStringConcatenation {