Вопрос-ответ

StringBuilder vs String concatenation in toString() in Java

StringBuilder против конкатенации строк в toString() в Java

Учитывая 2 toString() реализации ниже, какая из них предпочтительнее:

public String toString(){
return "{a:"+ a + ", b:" + b + ", c: " + c +"}";
}

или

public String toString(){
StringBuilder sb = new StringBuilder(100);
return sb.append("{a:").append(a)
.append(", b:").append(b)
.append(", c:").append(c)
.append("}")
.toString();
}

?

Что еще более важно, учитывая, что у нас есть только 3 свойства, это может не иметь значения, но в какой момент вы переключились бы с + concat на StringBuilder?

Переведено автоматически
Ответ 1

Версия 1 предпочтительнее, потому что она короче, и компилятор фактически превратит ее в версию 2 - никакой разницы в производительности вообще нет.


Что еще более важно, учитывая, что у нас есть только 3 свойства, это может и не иметь значения, но в какой момент вы переключаетесь с concat на builder?


На этапе, когда вы выполняете конкатенацию в цикле - обычно это когда компилятор не может заменить StringBuilder сам.

Ответ 2

Ключ в том, пишете ли вы единую конкатенацию в одном месте или накапливаете ее с течением времени.

В приведенном вами примере нет смысла явно использовать StringBuilder . (Посмотрите на скомпилированный код для вашего первого случая.)

Но если вы создаете строку, например, внутри цикла, используйте StringBuilder .

Для пояснения, предполагая, что hugeArray содержит тысячи строк, используйте такой код:

...
String result = "";
for (String s : hugeArray) {
result = result + s;
}

очень расточительно расходует время и память по сравнению с:

...
StringBuilder sb = new StringBuilder();
for (String s : hugeArray) {
sb.append(s);
}
String result = sb.toString();
Ответ 3

В большинстве случаев вы не увидите реальной разницы между двумя подходами, но легко построить сценарий наихудшего случая, подобный этому:

public class Main
{
public static void main(String[] args)
{
long now = System.currentTimeMillis();
slow();
System.out.println("slow elapsed " + (System.currentTimeMillis() - now) + " ms");

now = System.currentTimeMillis();
fast();
System.out.println("fast elapsed " + (System.currentTimeMillis() - now) + " ms");
}

private static void fast()
{
StringBuilder s = new StringBuilder();
for(int i=0;i<100000;i++)
s.append("*");
}

private static void slow()
{
String s = "";
for(int i=0;i<100000;i++)
s+="*";
}
}

Результат таков:

slow elapsed 11741 ms
fast elapsed 7 ms

Проблема в том, что to += добавление к строке восстанавливает новую строку, поэтому это стоит примерно линейно длине ваших строк (сумме обоих).

Итак, к вашему вопросу:

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

Ответ 4

Я предпочитаю:

String.format( "{a: %s, b: %s, c: %s}", a, b, c );

... потому что это коротко и читабельно.

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

Я согласен, что если вам приходится выводить много параметров, эта форма может сбить с толку (как сказано в одном из комментариев). В этом случае я бы переключился на более читаемую форму (возможно, используя ToStringBuilder из apache-commons - взято из ответа мэтта б) и снова проигнорировал производительность.

java performance string