Строки неизменяемы - это значит, что я никогда не должен использовать + = и только StringBuffer?

Строки неизменяемы, то есть после их создания они не могут быть изменены.

Итак, означает ли это, что для добавления вещей с + = потребуется больше памяти, чем если бы вы создали StringBuffer и добавленный текст?

Если вы используете + =, вы каждый раз должны создавать новый "объект", который должен быть сохранен в памяти, не так ли?

Ответ 1

Да, каждый раз вы создадите новый объект с + =. Однако это не значит, что это всегда неправильно. Это зависит от того, хотите ли вы это значение в виде строки или собираетесь ли вы использовать ее для дальнейшего построения строки.

Если вы действительно хотите получить результат x + y как строку, тогда вы можете просто использовать конкатенацию строк. Однако, если вы действительно собираетесь округлить раунд и добавить другую строку, а другую и т.д. - нужен только результат в виде строки в самом конце, тогда StringBuffer/StringBuilder - это путь. Действительно, цикл, на котором StringBuilder рассчитывает на конкатенацию строк, - разница в производительности для 5 или даже 10 прямых конкатенаций будет довольно небольшой, но для тысяч она становится намного хуже - в основном потому, что вы получаете O (N 2) с конкатенацией и сложностью O (N) с помощью StringBuilder.

В Java 5 и выше вы должны в основном использовать StringBuilder - он несинхронизирован, но это почти всегда нормально; очень редко нужно делиться между потоками.

У меня есть статья обо всем этом, которую вы можете найти полезной.

Ответ 2

Правило большого пальца проста:

Если вы выполняете конкатенации в цикле, не используйте +=

Если вы выполняете конкатенации не в цикле, использование += просто не имеет значения. (Если приложение, критичное к производительности,

Ответ 3

В Java 5 или более поздней версии StringBuffer является потокобезопасным, и поэтому имеет некоторые накладные расходы, которые вам не нужно платить, если вам это не нужно. StringBuilder имеет тот же API, но не является потокобезопасным (т.е. Вы должны использовать его только внутри одного потока).

Да, если вы создаете большие строки, более эффективно использовать StringBuilder. Вероятно, не стоит передавать StringBuilder или StringBuffer как часть вашего API. Это слишком запутанно.

Ответ 4

Я согласен со всеми ответами, изложенными выше, но это поможет вам немного понять, как реализуется Java. JVM внутренне использует StringBuffers для компиляции оператора String + (из StringBuffer Javadoc):

Буферы строк используются компилятор для реализации двоичного оператор конкатенации строк+. Для Например, код:

     x = "a" + 4 + "c"

скомпилирован в эквивалент:

     x = new StringBuffer().append("a").append(4).append("c")
                           .toString()

Аналогично, x += "some new string" эквивалентно x = x + "some new string". Вы видите, где я собираюсь с этим?

Если вы выполняете много конкатенаций String, использование StringBuffer увеличит вашу производительность, но если вы выполняете только пару простых конкатенаций String, компилятор Java, вероятно, оптимизирует его для вас, и вы не заметите разница в производительности

Ответ 5

Да. Строка неизменна. Для случайного использования + = в порядке. Если операция + = интенсивна, вы должны обратиться к StringBuilder.

Ответ 6

Совершенно верно. Вы должны использовать StringBuilder, хотя если безопасность потоков не является проблемой.

В качестве побочного примечания: может быть несколько объектов String, использующих ту же поддержку char [] - например, всякий раз, когда вы используете substring(), новый char [] не будет создан, что делает его довольно эффективным.

Кроме того, компиляторы могут сделать некоторую оптимизацию для вас. Например, если вы делаете

static final String FOO = "foo";
static final String BAR = "bar"; 

String getFoobar() {
  return FOO + BAR; // no string concatenation at runtime
}

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

Ответ 7

Но сборщик мусора в конечном итоге освободит старые строки, если нет ссылок на них

Ответ 8

Я думаю, он полагается на GC для сбора памяти с заброшенной строкой. Поэтому выполнение + = с построителем строк будет, безусловно, быстрее, если у вас много операций по манипулированию строками. Но это не должно быть проблемой для большинства случаев.

Ответ 9

Да, вы бы это сделали, и именно поэтому вы должны использовать StringBuffer, чтобы объединить много строк.

Также обратите внимание, что с Java 5 вы также должны предпочесть StringBuilder большую часть времени. Это просто какой-то несинхронизированный StringBuffer.

Ответ 10

Вы правы, что строки неизменяемы, поэтому, если вы пытаетесь сэкономить память при выполнении много конкатенации строк, вы должны использовать StringBuilder, а не + =.

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

Ответ 11

Нет

Он не будет использовать больше памяти. Да, создаются новые объекты, но старые перерабатываются. В конце концов, объем используемой памяти один и тот же.