Java: очистка содержимого StringBuffer - PullRequest
4 голосов
/ 31 октября 2010

Все,

Мне было интересно, имеет ли смысл очистка содержимого StringBuffer с помощью setLength (0).т.е. лучше сделать:

while (<some condition>)
{
    stringBufferVariable = new StringBuffer(128);
    stringBufferVariable.append(<something>)
                        .append(<more>)
                        ... ;
    Append stringBufferVariable.toString() to a file;
    stringBufferVariable.setLength(0);
}

Мои вопросы:
1> Будет ли это по-прежнему иметь лучшую производительность, чем объект String для добавления содержимого?

Я не совсем уверен, как повторная инициализация переменной StringBuffer повлияет на производительность и, следовательно, на вопрос.

Пожалуйста, добавьте свои комментарии

[править]: Удален второй вопросо сравнении со StringBuilder, так как я понял, что больше нечего изучать, основываясь на ответах.

Ответы [ 6 ]

7 голосов
/ 31 октября 2010

Лучше, чем объединение строк?

Если вы спрашиваете,

stringBufferVariable.append("something")
                    .append("more");
...

будет работать лучше, чем конкатенация с +, тогда да, обычно. Вот и вся причина, по которой эти классы существуют. Создание объекта обходится дороже по сравнению с обновлением значений в массиве char.

Похоже, что большинство, если не все компиляторы, теперь преобразуют конкатенацию строк в использование StringBuilder в простых случаях, таких как str = "something" + "more" + "...";. Единственное различие в производительности, которое я вижу, состоит в том, что компилятор не будет иметь преимущества при установке начального размера. Контрольные показатели скажут вам, достаточно ли разницы, чтобы иметь значение. Использование + сделает код более читабельным.

Из того, что я прочитал, компилятор, очевидно, не может оптимизировать конкатенацию, выполняемую в цикле, когда это что-то вроде

String str = "";
for (int i = 0; i < 10000; i++) {
    str = str + i + ",";
}

так что в этих случаях вы все равно захотите явно использовать StringBuilder.

StringBuilder против StringBuffer

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

Если вы используете setLength?

То, как в настоящее время пишется ваш пример, я не думаю, что вызов setLength что-то вам даст, так как вы создаете новый StringBuffer при каждом проходе цикла. Что вы действительно должны сделать, это

StringBuilder sb = new StringBuilder(128);
while (<some condition>) {
    sb.append(<something>)
      .append(<more>)
      ... ;
    // Append stringBufferVariable.toString() to a file;
    sb.setLength(0);
}

Это позволяет избежать ненужного создания объекта, и setLength будет обновлять только внутреннюю переменную int в этом случае.

3 голосов
/ 31 октября 2010

Я просто сосредоточился на этой части вопроса. (Остальные части задавались и отвечали много раз прежде на SO.)

Мне было интересно, имеет ли смысл очистка содержимого StringBuffer с помощью setLength (0).

Это зависит от библиотек классов Java, которые вы используете. В некоторых старых выпусках Sun от Java StringBuffer.toString () был реализован в предположении, что вызов sb.toString() - это последнее, что делается с буфером. Исходный массив поддержки StringBuffer становится частью String, возвращаемой toString(). Последующая попытка использовать StringBuffer привела к созданию и инициализации нового резервного массива путем копирования содержимого String. Таким образом, повторное использование StringBuffer при попытке вашего кода на самом деле замедлит работу приложения.

В Java 1.5 и более поздних версиях лучший способ кодирования выглядит следующим образом:

    bufferedWriter.append(stringBufferVariable);
    stringBufferVariable.setLength(0);

Это должно скопировать символы непосредственно из StringBuilder в буфер файлов без необходимости создания временной строки. При условии, что объявление StringBuffer находится за пределами цикла, setLength (0) позволяет вам повторно использовать буфер.

Наконец, вам следует беспокоиться обо всем этом, только если у вас есть доказательства того, что эта часть кода является (или может быть) узким местом. «Преждевременная оптимизация - корень всего зла», бла, бла.

1 голос
/ 31 октября 2010

Для вопроса 2 StringBuilder будет работать лучше, чем StringBuffer.StringBuffer является потокобезопасным, то есть методы синхронизированы.Строитель строк не синхронизирован.Так что, если ваш код будет выполняться ОДНЫМ потоком, то StringBuilder будет иметь лучшую производительность, так как он не требует дополнительных затрат на синхронизацию.

Как предлагает camickr, пожалуйста, обратитесь к API для StringBuffer и StringBuilder для получения дополнительной информации.

Также вас может заинтересовать эта статья: Печальная трагедия театра микрооптимизации

0 голосов
/ 31 октября 2010

да!setLength(0) отличная идея!вот для чего это.что-нибудь быстрее будет отказаться от stringBuffer и сделать новый.быстрее, ничего не скажешь об эффективности памяти :)

0 голосов
/ 31 октября 2010

Возможно, я что-то неправильно понимаю в вашем вопросе ... почему вы устанавливаете длину в 0 в нижней части, если вы просто создаете новую в начале каждой итерации?

Предполагая, что переменнаялокальная переменная для метода или то, что она не будет использоваться несколькими потоками, если она объявлена ​​вне метода (если она находится вне метода, в котором ваш код, вероятно, имеет проблемы), тогда сделайте его StringBuilder.* Если вы объявляете StringBuilder вне цикла, вам не нужно создавать новый при каждом входе в цикл, но вы захотите установить длину равной 0 в конце цикла.

Если вы объявляете StringBuilder внутри цикла, вам не нужно устанавливать длину равной 0 в конце цикла.

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

0 голосов
/ 31 октября 2010

1> Будет ли это иметь лучшую производительность, чем объект String для добавления содержимого?

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

2> Если использование StringBuilder будет работать лучше, чем StringBuffer, то почему?

Вы читали описание API для StringBuilder и / или StringBuffer? Этот выданный адрес там.

Я не совсем уверен, как повторная инициализация переменной StringBuffer повлияет на производительность и, следовательно, вопрос.

Хорошо создайте тестовую программу. Создайте тест, который каждый раз создает новый StringBuffer / Builder. Затем повторите тест и просто сбросьте символы на 0, а затем сравните время.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...