Бенчмаркинг производительности: String и String Builder

В этой статье мы проведем сравнительный анализ производительности классов String и StringBuilder в Java и обсудим, как эффективно модифицировать строки.

Строки в Java неизменяемы; модификация строки создает в памяти кучи новый объект String с последним содержимым, а исходная строка никогда не изменяется.

Неизменяемость

  String str = "You cannot modify "
  str = str + "me"
Вход в полноэкранный режим Выйти из полноэкранного режима

Когда мы добавляем значение «me» к переменной str, создается новый объект String с новым значением You cannot modify me и присваивается str. Исходная строка You cannot modify не изменяется.

Производительность

Частое изменение строк, например, с помощью оператора +, имеет значительные проблемы с производительностью, каждый раз, когда используется + append, создается и переназначается новый объект String.

Для эффективной модификации строк следует использовать StringBuilder, который изменяет строку и не создает дополнительный объект в памяти кучи.

Модификация строк

Для модификации строки используйте класс StringBuilder; при этом не создается новый объект String, а изменяется существующий.

  StringBuilder str = new StringBuilder("You can modify.");
  str.append("me");
Вход в полноэкранный режим Выход из полноэкранного режима

Бенчмаркинг производительности

Рассмотрим эталон производительности операции concatenation с помощью String и StringBuilder; рассмотрим следующее.

  • Рассмотрим 10 точек данных
    • inputSample = [100k, 200k, 300k, 400k, 500k, 600k, 700k, 800k, 900k, 1m].
    • Начнем с пустой строки и конкатенируем строку «a» n раз, где n = inputSample[i], т.е. n = 700k.
    • Мы хотим узнать, сколько времени потребуется для конкатенации строки «a» n раз для inputSample с использованием String и StringBuilder.

Класс String

public class StringBenchmark {
    public static void main(String[] args) {
        String appendCharacter = "a";

        int inputSample[] = new int[]{
                100000, 200000, 300000, 400000,
                500000, 600000, 700000, 800000,
                900000, 1000000};

        for (int n : inputSample) {
            double startTime = System.nanoTime();
            testStringAppend(n, "", appendCharacter);
            double endTime = System.nanoTime();
            double duration = (endTime - startTime) / 1000000000;
            String seconds = String.format("%.2f", duration);
            System.out.println("n = " + n + ": seconds: " + seconds);
        }
    }

    static void testStringAppend(int n, String str, String appendCharacter) {
        for (int i = 1; i <= n; i++) {
            str += appendCharacter;
        }
    }
}
Вход в полноэкранный режим Выход из полноэкранного режима
Строковый класс Результаты
n = 100000: seconds: 0.38
n = 200000: seconds: 0.99
n = 300000: seconds: 2.14
n = 400000: seconds: 3.74
n = 500000: seconds: 5.79
n = 600000: seconds: 8.28
n = 700000: seconds: 11.16
n = 800000: seconds: 14.65
n = 900000: seconds: 18.29
n = 1000000: seconds: 22.43
Вход в полноэкранный режим Выйти из полноэкранного режима

Класс StringBuilder

public class StringBuilderBenchmark {
    public static void main(String[] args) {
        String appendCharacter = "a";

        int inputSample[] = new int[]{
                100000, 200000, 300000, 400000,
                500000, 600000, 700000, 800000,
                900000, 1000000};

        for(int n: inputSample){
            double startTime = System.nanoTime();
            testStringAppend(n, new StringBuilder(""), appendCharacter);
            double endTime = System.nanoTime();
            double duration = (endTime - startTime)/1000000000;
            String seconds = String.format("%.7f", duration);
            System.out.println("n = "+n+": seconds: "+seconds);
        }
    }
    static void testStringAppend(int n, StringBuilder str, String appendCharacter){
        for(int i = 1; i <= n; i++){
            str.append(appendCharacter);
        }
    }
}
Войти в полноэкранный режим Выйти из полноэкранного режима
n = 100000: seconds: 0.0027
n = 200000: seconds: 0.0013
n = 300000: seconds: 0.0015
n = 400000: seconds: 0.0015
n = 500000: seconds: 0.0018
n = 600000: seconds: 0.0022
n = 700000: seconds: 0.0026
n = 800000: seconds: 0.0029
n = 900000: seconds: 0.0032
n = 1000000: seconds: 0.0036

Ввести полноэкранный режим Выход из полноэкранного режима

Время выполнения: Append

Ввод (n) Строка (S) Конструктор строк (S)
100k 0.38 0.0027
200k 0.99 0.0013
300k 2.14 0.0015
400k 3.74 0.0015
500k 5.79 0.0018
600k 8.28 0.0022
700k 11.16 0.0026
800k 14.65 0.0029
900k 18.29 0.0032
1m 22.43 0.0036

Вывод

  • StringBuilder работает значительно быстрее класса String при выполнении операций concatenation или modification.
  • Модификация строки создает новую строку в памяти кучи. Чтобы изменить содержимое String, мы должны обратиться к классу StringBuilder.
  • Любая попытка модифицировать класс String создает новый объект в памяти кучи, что имеет значительные недостатки в производительности.
  • StringBuilder идеально подходит для модификации содержимого строки; он делает это без создания дополнительных объектов в памяти.

Оцените статью
devanswers.ru
Добавить комментарий