Является ли цепочка StringBuilder.append более эффективной, чем конкатенация строк?

В соответствии с подсказкой Netbeans с именем Использовать цепочку методов .append вместо конкатенации строк

Вызывает конкатенацию строк в параметре вызова метода добавления StringBuilder или StringBuffer.

Является ли StringBuilder.append() более эффективным, чем конкатенация строк?

Пример кода

StringBuilder sb = new StringBuilder();
sb.append(filename + "/");

против.

StringBuilder sb = new StringBuilder();
sb.append(filename).append("/");

Ответ 1

Вы должны сбалансировать читаемость с функциональностью.

Скажем, у вас есть следующее:

String str = "foo";
str += "bar";
if(baz) str += "baz";

Это создаст 2 строковых сборщика (где вам действительно нужно 1, действительно) плюс дополнительный строковый объект для промежуточного. Вы бы стали более эффективными, если бы пошли:

StringBuilder strBuilder = new StringBuilder("foo");
strBuilder.append("bar");
if(baz) strBuilder.append("baz");
String str = strBuilder.toString();

Но, по сути, я думаю, что первый выглядит просто отлично. Преимущество производительности создания одного объекта кажется мне очень минимальным. Теперь, если вместо 3 строк у вас было 10 или 20 или 100, я бы сказал, что производительность перевешивает стиль. Если бы это было в цикле, я бы, конечно же, использовал построитель строк, но я думаю, что всего лишь пару строк отлично подходит для "неаккуратного" способа сделать код более чистым. Но... у этого есть очень опасная ловушка, скрывающаяся в нем! Читайте ниже (пауза, чтобы построить неопределенность... dun dun dunnnn)

Есть те, кто говорит, что всегда использует явный строковый конструктор. Одно из обоснований заключается в том, что ваш код будет продолжать расти, и он обычно будет делать это так же, как он уже (т.е. они не будут тратить время на рефакторинг.) Таким образом, вы получаете те 10 или 20 заявлений, каждый из которых создает их собственный строитель, когда вам это не нужно. Поэтому, чтобы предотвратить это с самого начала, они говорят, что всегда используют явный конструктор.

Итак, в то время как в вашем примере это не будет особенно быстрым, когда кто-то в будущем решает, что им нужно расширение файла в конце, или что-то в этом роде, если они продолжат использовать конкатенацию строк вместо StringBuilder, они "В конечном итоге вы столкнетесь с проблемами производительности.

Нам также нужно думать о будущем. Скажем, вы делали Java-код обратно в JDK 1.1, и у вас был следующий метод:

public String concat(String s1, String s2, String s3) {
    return s1 + s2 + s3;
}

В то время это было бы медленным, потому что StringBuilder не существовал.

Затем в JDK 1.3 вы решили сделать это быстрее с помощью StringBuffer (StringBuilder еще не существует). Вы делаете это:

public String concat(String s1, String s2, String s3) {
    StringBuffer sb = new StringBuffer();
    sb.append(s1);
    sb.append(s2);
    sb.append(s3);
    return sb.toString();
}

Это происходит намного быстрее. Отлично!

Теперь выходит JDK 1.5, и с ним идет StringBuilder (который быстрее, чем StringBuffer) и автоматическая транслировка

return s1 + s2 + s3;

к

return new StringBuilder().append(s1).append(s2).append(s3).toString();

Но вы не получаете это преимущество в производительности, потому что используете StringBuffer явно. Поэтому, будучи умным, вы вызвали удар производительности, когда Java стала умнее вас. Поэтому вы должны иметь в виду, что есть вещи, о которых вы не подумаете.

Ответ 2

Ну, ваш первый пример, по сути, переводится компилятором во что-то по строкам:

StringBuilder sb = new StringBuilder();
sb.append(new StringBuilder().append(filename).append("/").toString());

так что да, здесь есть определенная неэффективность. Однако, действительно ли это имеет значение в вашей программе, это другой вопрос. Помимо сомнительного стиля (намек: субъективный), это обычно имеет значение, если вы делаете это в плотной петле.

Ответ 3

Ни один из ответов до сих пор явно не касается конкретного случая, для которого намек. Он не говорит, чтобы всегда использовать StringBuilder#append вместо конкатенации. Но, если вы уже используете StringBuilder, нет смысла смешивать в конкатенации, потому что он создает избыточный StringBuilder (см. ответ Dirk) и ненужный временный экземпляр String.

В нескольких ответах уже обсуждается, почему предложенный способ более эффективен, но главное, если у вас уже есть экземпляр StringBuilder, просто назовите append на нем. Это так же читаемо (по-моему, и, видимо, тот, кто написал подсказку NetBeans), так как вы звоните append в любом случае, и это немного более эффективно.

Ответ 4

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

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

Ответ 5

Теоретически, да. Поскольку объекты String неизменяемы: после их создания они больше не могут быть изменены. Таким образом, использование "+" (конкатенация) в основном создает новый объект каждый раз.

Практически нет. Компилятор достаточно умен, чтобы заменить все ваши "+" на добавления StringBuilder.

Для более подробного объяснения: http://kaioa.com/node/59

PS: Netbeans??? Давай!

Ответ 6

Конкат двух строк быстрее использует эту функцию.

Однако, если у вас несколько строк или другой тип данных, вы должны использовать StringBuilder либо явно, либо неявно. Использование + со строками неявно использует StringBuilder.