В данной статье, хотелось бы рассмотреть, разобрать, рассказать и показать, в чем же разница между методом append из класса
StringBuilder
и оператором +=
для String
. Здесь вопрос будет стоять не столько в областях применения, сколько в оптимизации кода.
Да, бесспорно не углублявшийся в этот вопрос человек, скажет: "Зачем мне заменять оператор += созданием нового объекта вообще другого класса, после чего вызывать ещё и метод
toString()
? О какой оптимальности речь? Выбор ведь очевиден, ты о чем вообще?" и будет совершенно не прав.
Одна из проблем состоит в том, что String
не является примитивом. String
- объект как и любой class
в Java, а как известно, в Java нет такого понятия как перегрузка операторов (Как например в С++), операторы определены только для примитивов, для любого же класса мы с вами не может переопределить никакой оператор. Именно поэтому операторы "+
" и "+
=" являются своего рода "костылями" библиотеки Java, а костыль всегда несет потери.
Собственно, давайте перестанем тянуть хвост за кота и перейдем к замерам. Вот простая программка замеряющая время "склеивания" строки с переменной цикла 100000 раз.
public class MainClass
{
private static long time;
public static void main(String[] args)
{
saveTime();
String s = "Привет";
for(int i = 0; i < 100000; ++i)
{
s+=i;
}
printDiff();
}
private static void saveTime()
{
time = System.currentTimeMillis();
}
private static void printDiff()
{
System.out.println((System.currentTimeMillis() - time) + "ms");
}
}
На моем компьютере в консоль вывелось 6815ms. Т.е моему компьютеру понадобилось почти 7 секунд, чтобы склеить эту строку.
Теперь же давайте заменим на StringBuilder и даже включим метод toString()
в замеры.
public class MainClass
{
private static long time;
public static void main(String[] args)
{
saveTime();
StringBuilder sb = new StringBuilder("Привет");
for(int i = 0; i < 100000; ++i)
{
sb.append(i);
}
String s = sb.toString();
printDiff();
}
private static void saveTime()
{
time = System.currentTimeMillis();
}
private static void printDiff()
{
System.out.println((System.currentTimeMillis() - time) + "ms");
}
}
Мой ПК сказал мне 10ms. Т.е 0.01 Секунды. Думаю, разница на практике весьма очевидна, грубо говоря в 700 раз append
отработал быстрее.
Вызвано это тем, что скорее всего "+
" и "+=
" и сами могут вызывать этот же append, но при этом пройдя долгий путь по костылям языка, чтобы понять, что такой оператор вообще есть и что он должен делать (последний абзац не более чем догадка, я не разработчик JVM и не знаю что там и как).
Это наглядный пример того, что лишний объект совершенно не всегда является затратным. Да, код станет на пару строк длиннее, но зато экономия времени в больших проектах может стать колоссальной. Прошу заметить, что замеры производились далеко не на офисном ПК с доисторическим процессором, а теперь представьте, какая разница будет на этом самом офисном компьютере, который с трудом тянет косынку.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ