Как может мы быть присвоить значение Переменной StringBuffer или StringBuilder?
StringBuffer sb=new StringBuffer("teststr");
Теперь я должен изменить значение сурьмы к "testString", не освобождая содержание. Я смотрю на метод, который может делать уроки непосредственно, не используя отдельное выделение памяти. Я думаю, что мы можем сделать это только после освобождения содержания.
Сначала следует отметить, что StringBuilder
обычно предпочтительнее StringBuffer
. Из собственного API StringBuffer
:
Начиная с релиза JDK 5, этот класс был дополнен эквивалентным классом, предназначенным для использования одним потоком,
StringBuilder
. КлассStringBuilder
обычно следует использовать предпочтительнее, чем этот, поскольку он поддерживает все те же операции, но работает быстрее, поскольку не выполняет синхронизацию.
Учитывая это, я буду придерживаться StringBuffer
до конца ответа, потому что это то, о чем вы спрашиваете; все, что делает StringBuffer
, делает и StringBuilder
... кроме синхронизации, которая, как правило, не нужна. Так что если вы не используете буфер в нескольких потоках, переход на StringBuilder
- простая задача.
StringBuffer sb = new StringBuffer("teststr");
"Теперь мне нужно изменить значение
sb
на"testString"
, не опустошая содержимое"
Итак, вы хотите, чтобы sb
имел в буфере String
значение "testString"
? Есть много способов сделать это, и я перечислю некоторые из них, чтобы проиллюстрировать, как использовать API.
Оптимальное решение: выполняется минимальное редактирование от "teststr"
до "testString"
. Быстрее этого сделать невозможно.
StringBuffer sb = new StringBuffer("teststr");
sb.setCharAt(4, 'S');
sb.append("ing");
assert sb.toString().equals("testString");
Это без необходимости перезаписывает "tr"
в "tr"
.
StringBuffer sb = new StringBuffer("teststr");
sb.replace(4, sb.length(), "String");
assert sb.toString().equals("testString");
Это включает сдвиги из-за deleteCharAt
и insert
.
StringBuffer sb = new StringBuffer("teststr");
sb.deleteCharAt(4);
sb.insert(4, 'S');
sb.append("ing");
assert sb.toString().equals("testString");
Теперь все немного иначе: он не знает волшебным образом, что у него есть "teststr"
, который нужно изменить на "testString"
; он предполагает только, что StringBuffer
содержит где-то по крайней мере одно вхождение "str"
, и что его нужно заменить на "String"
.
StringBuffer sb = new StringBuffer("strtest");
int idx = sb.indexOf("str");
sb.replace(idx, idx + 3, "String");
assert sb.toString().equals("Stringtest");
Допустим, теперь вы хотите заменить ВСЕ вхождения "str"
и заменить его на "String"
. В StringBuffer
такая функциональность не встроена. Вы можете попытаться сделать это самостоятельно наиболее эффективным способом, либо in-place (возможно, с помощью двухпроходного алгоритма), либо используя второй StringBuffer
, и т.д.
Но вместо этого я буду использовать replace(CharSequence, CharSequence)
из String
. Этого будет более чем достаточно в большинстве случаев, и это определенно намного понятнее и проще в обслуживании. Она линейна по длине входной строки, поэтому асимптотически оптимальна.
String before = "str1str2str3";
String after = before.replace("str", "String");
assert after.equals("String1String2String3");
"Я ищу метод присвоения значения позже, используя предыдущее место в памяти"
Точное место в памяти не должно вас волновать; на самом деле, и StringBuilder
, и StringBuffer
будут перераспределять свой внутренний буфер в разные места памяти, когда это необходимо. Единственным способом предотвратить это будет ensureCapacity
(или установить его через конструктор), чтобы внутренний буфер всегда был достаточно большим и его никогда не нужно было бы перераспределять.
Однако, даже если StringBuffer
время от времени перераспределяет свой внутренний буфер, это не должно быть проблемой в большинстве случаев. Большинство структур данных, которые динамически растут (ArrayList
, HashMap
и т.д.), делают это таким образом, чтобы сохранить алгоритмически оптимальные операции, используя преимущества амортизации затрат. Я не буду рассматривать здесь анализ амортизации, но если вы не занимаетесь системами реального времени и т.д., это не должно быть проблемой для большинства приложений.
Очевидно, что я не знаю специфики ваших потребностей, но есть опасение преждевременной оптимизации, поскольку вы, кажется, беспокоитесь о вещах, о которых большинство людей имеют роскошь никогда не беспокоиться.
Вы можете использовать StringBuilder
вместо StringBuffer
, что обычно и делают люди, если могут ( StringBuilder
не синхронизируется, поэтому он быстрее, но не безопасен). Если вам нужно инициализировать содержимое одного файла другим, используйте метод toString ()
для получения строкового представления. Чтобы повторно использовать существующий StringBuilder
или StringBuffer
, просто вызовите setLength (0)
.
Редактировать
Вы можете перезаписать ряд элементов с помощью функции replace ()
. Чтобы изменить все значение на newval
, вы должны использовать buffer.replace (0, buffer.length (), newval)
. См. Также:
Возможно, вы ищете метод replace () для StringBuffer:
StringBuffer sb=new StringBuffer("teststr");
sb.replace(0, sb.length() - 1, "newstr");
Внутренне он удаляет исходную строку, затем вставляет новую строку, но это может избавить вас от этого:
StringBuffer sb=new StringBuffer("teststr");
sb.delete(0, sb.length() - 1);
sb.append("newstr");
Использование setLength (0) переназначает StringBuffer нулевой длины для переменной, что, я думаю, не то, что вам нужно:
StringBuffer sb=new StringBuffer("teststr");
// Reassign sb to a new, empty StringBuffer
sb.setLength(0);
sb.append("newstr");
Вы можете преобразовать в / из String следующим образом:
StringBuffer buf = new StringBuffer();
buf.append("s1");
buf.append("s2");
StringBuilder sb = new StringBuilder(buf.toString());
// Now sb, contains "s1s2" and you can further append to it
Что вы имеете в виду под словом «переназначить»? Вы можете очистить содержимое, используя setLength ()
, а затем начать добавлять новое содержимое, если вы это имеете в виду.
Изменить : для изменения частей содержимого вы можете использовать replace ()
.
Как правило, на этот вопрос можно легко ответить, просмотрев документацию по API соответствующих классов.
В самом деле, я думаю, что replace ()
- лучший способ. Я проверил исходный код Java. Он действительно перезаписывает старые символы.
Вот исходный код replace ():
public AbstractStringBuffer replace(int start, int end, String str)
{
if (start < 0 || start > count || start > end)
throw new StringIndexOutOfBoundsException(start);
int len = str.count;
// Calculate the difference in 'count' after the replace.
int delta = len - (end > count ? count : end) + start;
ensureCapacity_unsynchronized(count + delta);
if (delta != 0 && end < count)
VMSystem.arraycopy(value, end, value, end + delta, count - end);
str.getChars(0, len, value, start);
count += delta;
return this;
}