Лучшие практики / производительность: смешивание StringBuilder.append с String.concat

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

StringBuilder sb = new StringBuilder("AAAAAAAAAAAAA")
    .append(B_String).append("CCCCCCCCCCC").append(D_String)
    .append("EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE")
    .append("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");

Это способ сделать это? Из этого поста я заметил, что + Оператор Strings создает новый экземпляр StringBuilder, объединяет операнды и возвращает преобразование String, которое кажется гораздо более трудоемким, чем просто вызов .append(); так что если это правда, то об этом не может быть и речи. Но что насчет String.concat()? Правильно ли использовать .append() для каждого объединения? Или только для переменных, и литералы можно добавить с .concat()?

StringBuilder sb = new StringBuilder("AAAAAAAAAAAAA")
    .append(B_String.concat("CCCCCCCCCCC")).append(D_String
    .concat("EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE")
    .concat("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"));

Каковы общие правила для лучших практик и производительности для решения этих ситуаций? Правильно ли мое предположение о + а на самом деле его просто нельзя использовать?

7 ответов

Решение

+ оператор

String s = s1 + s2

За кулисами это переводится:

String s = new StringBuilder(s1).append(s2).toString();

Представьте, сколько дополнительной работы он добавляет, если у вас есть s1 + s2 Вот:

stringBuilder.append(s1 + s2)

вместо:

stringBuilder.append(s1).append(s2)

Несколько строк с +

Стоит отметить, что:

String s = s1 + s2 + s3 + ... +sN

переводится на:

String s = new StringBuilder(s1).append(s2).append(s3)...apend(sN).toString();

concat()

String s = s1.concat(s2);

String создает char[] массив, который может соответствовать как s1 а также s2, Копии s1 а также s2 содержимое этого нового массива. На самом деле требует меньше работы, чем + оператор.

StringBuilder.append()

Поддерживает внутренний char[] массив, который растет при необходимости. Без дополнительных char[] создается, если внутренний достаточно большой.

stringBuilder.append(s1.concat(s2))

также плохо работает, потому что s1.concat(s2) создает дополнительный char[] массив и копии s1 а также s2 чтобы просто скопировать это новое содержимое массива во внутренний StringBuilderchar[],

Это, как говорится, вы должны использовать append() все время и добавляйте необработанные строки (ваш первый фрагмент кода правильный).

Компилятор оптимизирует + конкатенацию.

Так

int a = 1;
String s = "Hello " + a;

превращается в

new StringBuilder().append("Hello ").append(1).toString();

Здесь отличная тема, объясняющая, почему вы должны использовать оператор +.

Оптимизация выполняется автоматически компилятором.

Компилятор Java2 автоматически преобразует следующее:

String s = s1 + s2; 

в

String s = (new StringBuffer()).append(s1).append(s2).toString();

Взято прямо с веб-сайта Java Best Practices on Oracles.

Вы должны всегда использовать append,

concat создать новую строку, так что это очень похоже на + Я думаю.

если ты concat или использовать + с 2 final String JVM может выполнить оптимизацию, так что это то же самое, что и добавить в этом случае.

Если вы объединяете ровно две строки, используйте String.concat (создает новую строку, создавая новый массив символов, который соответствует обеим строкам и копирует в него массивы обеих строк).

Если вы объединяете несколько (более двух) строк в одну строку, используйте + или StringBuilder.append, это не имеет значения, так как компилятор преобразует + в StringBuilder.append. Это хорошо для нескольких строк, поскольку поддерживает один массив символов, который увеличивается по мере необходимости.

Если вы объединяете несколько строк в несколько строк, создайте один StringBuilder и используйте метод append. В конце концов, когда вы закончите добавление Strings в StringBuilder, используйте его.toString()- метод для создания String из него. Для объединения в несколько строк это быстрее, чем во втором методе, поскольку второй метод будет создавать новый StringBuilder в каждой строке, добавлять строки и затем приводить обратно к String, в то время как третий метод использует только один StringBuilder для всего этого.

Я лично предпочитаю Strings.format(), простой и удобный форматировщик однострочных строк.

String b = "B value";
String d = "D value";
String fullString = String.format("A %s C %s E F", b, d);
// Output: A B value C D value E F

Использование + Оператор - лучшая практика, он также прост и читабелен.

Язык Java обеспечивает специальную поддержку оператора конкатенации строк ( +) и преобразования других объектов в строки. Конкатенация строк реализуется с помощью класса StringBuilder(или StringBuffer) и его метода добавления.

Официальный документ: https://docs.oracle.com/javase/8/docs/api/java/lang/String.html

Все ответы довольно хороши и понятны. Но я чувствовал, что изучение других методов конкатенации строк также может помочь, например, Guava Joiner, Streams, String.format и т. Д.

Для получения полной информации о производительности каждого метода конкатенации https://redfin.engineering/java-string-concatenation-which-way-is-best-8f590a7d22a8.

Вкратце, производительность конкатенации зависит от номера. строк для объединения. Например, для объединения 1-10 строк лучше всего подходят эти методы - StringBuilder, StringBuffer и Plus Operator. А для объединения сотен строк - Guava Joiner, библиотека apache stringsUtils также отлично работает.

Просмотрите указанный выше блог. Это действительно очень хорошо объясняет эффективность работы.

Спасибо.

На уровне байт-кода ничего не отличается, и мы не ставим под угрозу эффективность. В случае выполнения уровня байтового кода, он должен пройти через не встроенный метод перегрузки операторов для +, вызвав append. затем на уровне языка ассемблера (Java написана на C, а C производит сборки, аналогичные сборкам, будет дополнительный вызов регистра для вызова store + метода в стеке и будет дополнительный push. (на самом деле, кросс-компилятор может оптимизировать оператор + звоните, в этом случае не делая различий с эффективностью.)

Хорошей практикой является наличие одного способа повысить удобочитаемость.:)

Другие вопросы по тегам