Оператор конкатенации (+) против concat()

Для конкатенации строк мы можем использовать либо оператор concat(), либо concat (+).

Я пробовал следующий тест производительности и нашел, что concat() работает быстрее, и эффективный способ записи для конкатенации строк.

Сравнение конкатенации строк за 100 000 раз:

String str = null;

//------------Using Concatenation operator-------------
long time1 = System.currentTimeMillis();
long freeMemory1 = Runtime.getRuntime().freeMemory();

for(int i=0; i<100000; i++){
    str = "Hi";
    str = str+" Bye";
}
long time2 = System.currentTimeMillis();
long freeMemory2 = Runtime.getRuntime().freeMemory();

long timetaken1 = time2-time1;
long memoryTaken1 = freeMemory1 - freeMemory2;
System.out.println("Concat operator  :" + "Time taken =" + timetaken1 +
                   " Memory Consumed =" + memoryTaken1);

//------------Using Concat method-------------
long time3 = System.currentTimeMillis();
long freeMemory3 = Runtime.getRuntime().freeMemory();
for(int j=0; j<100000; j++){
    str = "Hi";
    str = str.concat(" Bye");
}
long time4 = System.currentTimeMillis();
long freeMemory4 = Runtime.getRuntime().freeMemory();
long timetaken2 = time4-time3;
long memoryTaken2 = freeMemory3 - freeMemory4;
System.out.println("Concat method  :" + "Time taken =" + timetaken2 +
                   " Memory Consumed =" + memoryTaken2);

Результат

Concat operator: Time taken = 31; Memory Consumed = 2259096
Concat method  : Time taken = 16; Memory Consumed = 299592

Если concat() быстрее, чем оператор, тогда, когда мы должны использовать оператор конкатенации (+)?

Ответ 1

Метод concat всегда создает новую строку с результатом конкатенации.

Оператор плюс поддерживается созданием StringBuilder, добавлением всех необходимых значений String и последующим вызовом toString().

Итак, если вам нужно объединить два значения, concat() будет лучшим выбором. Если вам нужно соединить 100 значений, вы должны использовать оператор плюс или явно использовать StringBuilder (например, в случае добавления в цикле).

Ответ 2

Фактически s1 + s2 и s1.concat(s2) очень различны.

s1 + s2 преобразуется javac в

(new StringBuilder(String.valueOf(s1)).append(s2).toString();

Вы можете увидеть это, если вы декомпилируете .class. Эта конструкция не очень эффективна; он включает до трех новых char [] распределений и трех операций копирования char [].

s1.concat(s2) всегда является одной новой операцией char [] + one copy, см. String.java

public String concat(String str) {
    int otherLen = str.length();
    if (otherLen == 0) {
        return this;
    }
    char buf[] = new char[count + otherLen];
    getChars(0, count, buf, 0);
    str.getChars(0, otherLen, buf, count);
    return new String(0, count + otherLen, buf);
}

Обратите внимание, что новый String (int, int, char []) является частным конструктором пакета String. Он использует char buf [] напрямую, без обычного копирования, чтобы гарантировать невидимость buf для неизменяемости String.

Ответ 3

Ваш тест должен работать не менее 2 секунд, при этом каждый цикл в отдельном методе должен быть значимым. Короткие тесты могут быть сложными для воспроизведения и сравнения. С вашего времени, похоже, вы используете Windows (т.е. Потому, что у вас время 16 и 31 мс;) Вместо этого попробуйте System.nanoTime(). Когда цикл повторяется более чем в 10 000 раз, весь метод компилируется. Это означает, что ваш более поздний метод уже скомпилирован, когда он запущен.

В ответ на ваш вопрос concat немного быстрее при добавлении двух строк. Тем не менее, он поставляется с типичными и концептуальными накладными расходами, которые, вероятно, будут намного больше, чем тот, который вы сохраните. Даже на основе ваших тестов, повторяющихся в 100 000 раз, это экономит менее 15 мс, и все же это обойдется вам гораздо больше, чем это в свое время (что, вероятно, будет стоить больше). Вы можете найти в будущей версии JVM, разница всегда оптимизирована, и сложность вашего кода все еще существует.


EDIT: я не заметил, что результат памяти был подозрительным.

String str = null;

//------------Using Concatenation operator-------------
long time1 = System.currentTimeMillis();
long freeMemory1 = Runtime.getRuntime().freeMemory();
for (int i = 0; i < 10000; i++) {
    str = "Hi";
    str = str + " Bye";
}
long time2 = System.currentTimeMillis();
long freeMemory2 = Runtime.getRuntime().freeMemory();

long timetaken1 = time2 - time1;
long memoryTaken1 = freeMemory1 - freeMemory2;
System.out.println("Concat operator  :" + "Time taken =" + timetaken1 + " Memory Consumed= " + memoryTaken1);

str = null;
//------------Using Concat method-------------
long time3 = System.currentTimeMillis();
long freeMemory3 = Runtime.getRuntime().freeMemory();
for (int j = 0; j < 10000; j++) {
    str = "Hi";
    str = str.concat(" Bye");

}
long time4 = System.currentTimeMillis();
long freeMemory4 = Runtime.getRuntime().freeMemory();

long timetaken2 = time4 - time3;
long memoryTaken2 = freeMemory3 - freeMemory4;
System.out.println("Concat method  :" + "Time taken =" + timetaken2 + " Memory Consumed= " + memoryTaken2);

печатает при запуске с -XX:-UseTLAB -mx1g

Concat operator  :Time taken =12 Memory Consumed= 1291456
Concat method  :Time taken =7 Memory Consumed= 560000

делает соотношение использования памяти около 2: 1. В исходном вопросе результат изменяется каждый раз, когда вы его запускаете, иногда .concat(), как представляется, использует больше.

Ответ 4

Я считаю, что "стиль" конкатенации будет иметь значение.

Для concat() он внутренне создает новый буфер массива char и возвращает новую строку на основе этого массива char.

Для оператора +, компилятор фактически переводит его на использование StringBuffer/StringBuilder.

Поэтому, если вы объединяете две строки, concat() определенно является лучшим выбором, потому что количество созданных объектов - это только результат, который используется в String (и буфере char, который используется внутри), при использовании оператора + быть переведены на:

result = strA + strB;
-- translate to -->
result = new StringBuilder(strA).append(strB).toString();

Создан дополнительный экземпляр StringBuilder.

Однако, если вы конкатенируете, например пять строк подряд, каждый concat() создаст новый объект String. При использовании оператора + компилятор преобразует оператор в один StringBuilder с несколькими операциями добавления. Это определенно экономит много лишнего временного экземпляра объекта:

result = strA + strB + strC + strD + strE;
-- translate to -->
result = new StringBuilder(strA).append(strB).append(strC).append(strD).append(strE).toString();

Ответ 5

Вы можете всегда использовать +, если используете только >= Java 1.5, а не объявляете свою базовую строку (которую вы хотите объединить) за пределами петля. В Java 1.5 это приводит к созданию new StringBuilder и работе над ним до завершения вашей строки. Это самый быстрый способ.

В любом случае - если вы находитесь в цикле (и объединяете строки с +) - каждая итерация цикла создает new StringBuilder - это не лучшая идея. Таким образом, вы должны принудительно использовать классы StringBuilder или StringBuffer (потокобезопасные).

Как правило, эта ссылка четко отвечает на ваш вопрос и дает вам полное знание:

http://littletutorials.com/2008/07/16/stringbuffer-vs-stringbuilder-performance-comparison/

Ответ 6

Хотя и оператор, и метод дают один и тот же результат, то, как они работают внутри, отличается.

Метод concat(), который просто объединяет str1 с str2 и выводит строку, более эффективен для небольшого количества конкатенаций.

Но с оператором конкатенации '+', str1+=str2; будет интерпретироваться как str1 = new StringBuilder().append(str1).append(str2).toString();

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

Ответ 7

В общем, это плохая практика для объединения строк с + и с concat(). Если вы хотите создать String, используйте StringBuilder.

Ответ 8

Собственно, оба варианта одинаковы. Если вы видите код concat(String paramString), он вернет новый объект строки, а в операторе (+) он также сгенерирует новый строковый объект.

Если вы не хотите создавать новый объект, используйте конструктор строк, чтобы объединить две строки.