В этой статье мы проведем сравнительный анализ производительности классов 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 идеально подходит для модификации содержимого строки; он делает это без создания дополнительных объектов в памяти.