5

Сложение строк: concat() против оператора "+"

14

Вопрос на 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 ответ(ов)

0

Я провел аналогичный тест, как и @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.

0

На данный момент, судя по вашим замерам, можно констатировать, что производительность операции конкатенации строк в 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. Однако в большинстве случаев, как показывают результаты, + также предлагает отличное соотношение производительности и простоты использования.

0

Ваше тестирование кажется интересным и показывает некоторые нюансы работы с конкатенацией строк в Java. Давайте разберемся с вашим вопросом.

Вы привели пример кода, в котором сравнили время выполнения двух способов объединения строк: с использованием String.concat() и оператора +. Результаты оказались неожиданными, так как concat() выполняется быстрее.

Давайте рассмотрим несколько моментов:

  1. Операции со строками: В Java строки неизменяемы (immutable), и каждый раз, когда вы выполняете операцию конкатенации, создается новая строка. Оператор + в Java может вызывать StringBuilder под капотом для оптимизации, особенно когда он используется в контексте, где известен размер строки заранее (например, в StringBuilder).

  2. Оптимизация компилятора: Java-компилятор (JIT) не всегда может оптимизировать конкатенации строк, используя +, особенно если вы выполняете много операций в цикле, как в вашем случае. Комpилятор может не распознать, что в каждом шаге создается одинаковая строка, что может привести к дополнительным накладным расходам.

  3. Переполнение строк: В случае с String.concat() каждый раз создается новая строка, так же как и для a + b, но метод concat() может быть оптимизирован по сравнению с использованием +, чтобы избежать дополнительных накладных расходов, связанных с управлением памятью и вызовами методов.

  4. Изменение кода: Для более эффективной конкатенации в таких ситуациях рекомендуется использовать StringBuilder или StringBuffer, особенно когда нужно объединить много строк. Например:

    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < 10000000; i++) {
        sb.append(a).append(b);
    }
    String result = sb.toString();
    

Таким образом, результаты ваших измерений могут быть вызваны различиями в оптимизации между различными подходами. Если вы хотите максимально увеличить производительность, использование StringBuilder будет более предпочтительным решением.

Пожалуйста, проводите тесты и делитесь результатами — это может быть полезным для понимания нюансов работы с строками в Java!

0

Существует два основных отличия между оператором + и методом concat.

  1. Если вы используете метод concat, то можете объединять только строки. В отличие от этого, при использовании оператора + вы можете объединять строку с любым другим типом данных.

    Например:

    String s = 10 + "Hello";
    

    В этом случае результат будет 10Hello.

    String s = "I";
    String s1 = s.concat("am").concat("good").concat("boy");
    System.out.println(s1);
    

    В этом случае необходимо предоставить две строки.

  2. Второе и главное отличие между + и 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. Наслаждайтесь! 😃

0

Оператор + может использоваться для объединения строки с другой строкой, символом, целым числом, числом с плавающей запятой (double) или float. В этом случае он просто преобразует второе значение в его строковое представление перед конкатенацией.

Оператор конкатенации (concat) может применяться только к строкам. Он проверяет совместимость типов данных и выдает ошибку, если они не совпадают.

Кроме этого, приведённый вами код выполняет те же самые действия.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь