Другой вопрос: почему вы используете SB только для одной итерации цикла? Есть ли еще одна внутренняя итерация? SB не подходит, если вы просто хотите сделать A + B + C + D (компилятор Java будет внутренне использовать SB). Это помогает, если вы хотите условно добавить части строк, но в противном случае ... просто используйте "+".
helios
Ответы:
135
Один из вариантов - использовать метод удаления следующим образом:
StringBuffer sb =newStringBuffer();for(int n =0; n <10; n++){
sb.append("a");// This will clear the buffer
sb.delete(0, sb.length());}
Другой вариант (очиститель бит) использует setLength (int len) :
sb.setLength(0);
См. Javadoc для получения дополнительной информации:
Немного менее бессмысленным было бы просто объявить StringBuffer внутри цикла.
Марк Эллиот,
11
А, я думаю sb.setLength (0); чище и эффективнее, чем объявление внутри цикла. Ваше решение идет вразрез с преимуществом использования StringBuffer в производительности ...
Джон
6
Я думаю, что выигрыш в производительности достигается за счет изменчивости строки, а не за счет сохранения экземпляра. вот быстрый тест итераций 1e8: внутренний цикл (2,97 с): ideone.com/uyyTL14w , внешний цикл (2,87 с): ideone.com/F9lgsIxh
Марк Эллиот
6
Кстати о производительности: если к вашему коду не обращаются в многопоточном сценарии, вам следует использовать StringBuilder, а не StringBuffer - см. Javadoc: «По возможности рекомендуется использовать этот класс вместо StringBuffer, поскольку он будет быстрее в большинство реализаций ".
Рахель Люти,
4
Единственное преимущество создания SB снаружи - это не потерять его внутренний (потенциально длинный) char []. Если в первом итераторе он достаточно вырос, то во втором цикле не нужно будет изменять размер char []. Но для получения преимущества «чистый метод» должен сохранить размер внутреннего массива. setLength делает это, но также устанавливает в \ u0000 все неиспользуемые символы в SB, поэтому он менее эффективен, чем простое создание нового SB с хорошей начальной емкостью. Объявление внутри цикла лучше.
helios,
48
Самый простой способ повторно использовать StringBuffer- использовать методsetLength()
sb.setLength(0);// It will just discard the previous data, which will be garbage collected later.
Или используйте:
sb.delete(0, sb.length());// A bit slower as it is used to delete sub sequence.
НОТА
Избегайте объявления StringBufferили StringBuilderобъектов внутри цикла, иначе он будет создавать новые объекты с каждой итерацией. Создание объектов требует системных ресурсов, места, а также времени. Поэтому в долгосрочной перспективе избегайте объявления их в цикле, если это возможно.
Я предлагаю создавать новый StringBuffer(или даже лучше StringBuilder) для каждой итерации. Разница в производительности действительно незначительна, но ваш код будет короче и проще.
Если у вас есть доказательства такой разницы в производительности, поделитесь ими. (Я также буду рад увидеть статистику того, где в основном используется Java, и под каким определением «в основном».)
Эли Ахеркан,
1
Хорошо известно, что выделение памяти (новое ключевое слово в Java) дороже, чем простое изменение некоторых полей одного и того же объекта. Что касается «в основном», на которое вы могли бы заменить слово «высоко», существует более 1,5 миллиарда Android-устройств, и все они используют Java.
Louis CAD
1
Я согласен с тем, что в некоторых случаях читаемость кода важнее производительности, но в данном случае это всего лишь одна строка кода! И вы можете запустить тест, который докажет вам, что выделение и создание объектов, а также сборка мусора обходятся дороже, чем не делать этого вообще. Поскольку мы в курсе, это более чем актуально.
Луи CAD
1
Я также присоединился к точке зрения Кнута, но его точка зрения не всегда верна. Добавление всего одной строчки для потенциального увеличения количества циклов процессора и памяти - это абсолютно не зло. Вы слишком прямолинейно понимаете идею. Обратите внимание, что цикл обычно повторяется много раз. Цикл может повторяться тысячи раз, что может съесть драгоценные мегабайты на мобильном телефоне (а также на сервере или компьютере), если его не оптимизировать тщательно.
Louis CAD
1
Я думаю, что мы оба достаточно ясно изложили нашу точку зрения, и я считаю, что дальнейшее обсуждение не принесет пользы для этого раздела комментариев. Если вы считаете, что мой ответ неверен, вводит в заблуждение или является неполным, то вы - или кто-либо другой - можете отредактировать его и / или проголосовать против него.
Уже есть хороший ответ. Просто добавьте результат теста для разницы в производительности StringBuffer и StringBuild, используйте новый экземпляр в цикле или используйте setLength (0) в цикле.
Резюме: в большом цикле
StringBuilder намного быстрее StringBuffer
Создание нового экземпляра StringBuilder в цикле не имеет разницы с setLength (0). (setLength (0) имеет очень-очень-очень маленькое преимущество, чем создание нового экземпляра.)
StringBuffer медленнее, чем StringBuilder, создавая новый экземпляр в цикле
setLength (0) из StringBuffer работает намного медленнее, чем создание нового экземпляра в цикле.
Очень простой тест (я просто вручную изменил код и провожу другой тест):
publicclassStringBuilderSpeed{publicstaticfinalchar ch[]=newchar[]{'a','b','c','d','e','f','g','h','i'};publicstaticvoid main(String a[]){int loopTime =99999999;long startTime =System.currentTimeMillis();StringBuilder sb =newStringBuilder();for(int i =0; i < loopTime; i++){for(char c : ch){
sb.append(c);}
sb.setLength(0);}long endTime =System.currentTimeMillis();System.out.println("Time cost: "+(endTime - startTime));}
}
Новый экземпляр StringBuilder в цикле: временные затраты: 3693, 3862, 3624, 3742
StringBuilder setLength: Стоимость времени: 3465, 3421, 3557, 3408
Новый экземпляр StringBuffer в цикле: временные затраты: 8327, 8324, 8284
StringBuffer setLength Стоимость времени: 22878, 23017, 22894
Снова StringBuilder setLength, чтобы убедиться, что у моей лаборатории не возникла проблема с использованием такой длины для StringBuffer setLength :-) Затраты времени: 3448
Ответы:
Один из вариантов - использовать метод удаления следующим образом:
Другой вариант (очиститель бит) использует setLength (int len) :
См. Javadoc для получения дополнительной информации:
источник
Самый простой способ повторно использовать
StringBuffer
- использовать методsetLength()
public void setLength(int newLength)
У вас может быть случай вроде
источник
setLength
вместоsetlength
.У вас есть два варианта:
Либо используйте:
Или используйте:
НОТА
Избегайте объявления
StringBuffer
илиStringBuilder
объектов внутри цикла, иначе он будет создавать новые объекты с каждой итерацией. Создание объектов требует системных ресурсов, места, а также времени. Поэтому в долгосрочной перспективе избегайте объявления их в цикле, если это возможно.источник
источник
Я предлагаю создавать новый
StringBuffer
(или даже лучшеStringBuilder
) для каждой итерации. Разница в производительности действительно незначительна, но ваш код будет короче и проще.источник
Использование:
по удобочитаемости считаю это лучшим решением.
источник
Уже есть хороший ответ. Просто добавьте результат теста для разницы в производительности StringBuffer и StringBuild, используйте новый экземпляр в цикле или используйте setLength (0) в цикле.
Резюме: в большом цикле
Очень простой тест (я просто вручную изменил код и провожу другой тест):
}
Новый экземпляр StringBuilder в цикле: временные затраты: 3693, 3862, 3624, 3742
StringBuilder setLength: Стоимость времени: 3465, 3421, 3557, 3408
Новый экземпляр StringBuffer в цикле: временные затраты: 8327, 8324, 8284
StringBuffer setLength Стоимость времени: 22878, 23017, 22894
Снова StringBuilder setLength, чтобы убедиться, что у моей лаборатории не возникла проблема с использованием такой длины для StringBuffer setLength :-) Затраты времени: 3448
источник
я думаю, что этот код быстрее.
источник