Почему требуется больше времени для объединения строк с помощью stringbuilder?

#java #stringbuilder

#java #stringbuilder

Вопрос:

Я нашел раздел в каком-то коде на работе, где куча длинных строк была создана с использованием этого формата:

 String s = ""  
    "...n"  
    "...n"  
  

Просто из любопытства решил провести быстрый тест, чтобы увидеть, будет ли StringBuilder иметь какое-либо заметное значение.

 public class TestStringConcat {

    public static void main(String[] args) {
        int arraySize = 1000000;
        String[] strings1 = new String[arraySize];
        String[] strings2 = new String[arraySize];

        System.out.println("Testing concat version");

        long startTime = System.currentTimeMillis();
        for (int i = 0; i < arraySize; i  ) {
            strings1[i] = ""  
                "A big long multiline string"; //35 lines of string omitted 
        }

        long endTime = System.currentTimeMillis();
        System.out.println("Time to concat strings: "   (endTime - startTime));

        System.out.println("Now testing with stringbuilder ");
        startTime = System.currentTimeMillis();
        for (int i = 0; i < arraySize; i  ) {
            StringBuilder sb = new StringBuilder();
            sb.append("A big long multiline string"); //35 lines of string omitted 
            strings2[i] = sb.toString();
        }
        endTime = System.currentTimeMillis();
        System.out.println("Time to build strings with stringbuilder: "   (endTime - startTime));

    }

}
  

Вывод:

 Testing concat version
Time to concat strings: 5
Now testing with stringbuilder 
Time to build strings with stringbuilder: 2455
  

Я думал, что StringBuilders должен быть быстрее, но в данном случае это намного медленнее. Что происходит?

Комментарии:

1. Является ли время компиляции строк постоянным? Они выполняются во время компиляции, и вы только что замедлили работу.

Ответ №1:

Первая часть не выполняет никакой конкатенации. Объединение происходит во время компиляции. Все, что он делает, это сохраняет одну и ту же уникальную длинную строку во всех индексах массива.

При объединении в цикле следует использовать StringBuilder. Даже когда вы объединяете динамические данные во время выполнения с помощью

 "a"   someVar   "b"   someOtherVar;
  

Компилятор генерирует код, который использует StringBuilder для объединения (или использует код по крайней мере так же быстро, как это делал бы StringBuilder, в зависимости от версии Java).

Что является медленным, так это:

 String s = "";
for (String e : array) {
    s  = e;
}
  

Это создает много (ну, по одной на элемент массива) временных строк и множество копий этих временных строк в следующую строку.

Комментарии:

1. Просто думаю — в наши дни это неправильно, верно: » Компилятор генерирует код, который использует StringBuilder » — начиная с JEP280 «Индифицировать конкатенацию строк»

2. @BoristheSpider сгенерированный байтовый код не использует StringBuilder напрямую, а вместо этого использует indy, но я не знаю, что на самом деле используется в настоящее время фактической реализацией конкатенации строк, используемой StringConcatFactory, вызываемой indy. Я предполагаю, что он все еще использует StringBuilder. Я все равно перефразирую.