Как Повторно присвоить значение StringBuffer?

Как может мы быть присвоить значение Переменной StringBuffer или StringBuilder?

StringBuffer sb=new StringBuffer("teststr");

Теперь я должен изменить значение сурьмы к "testString", не освобождая содержание. Я смотрю на метод, который может делать уроки непосредственно, не используя отдельное выделение памяти. Я думаю, что мы можем сделать это только после освобождения содержания.

14
задан Arsaceus 4 February 2016 в 07:30
поделиться

7 ответов

Сначала следует отметить, что 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 и т.д.), делают это таким образом, чтобы сохранить алгоритмически оптимальные операции, используя преимущества амортизации затрат. Я не буду рассматривать здесь анализ амортизации, но если вы не занимаетесь системами реального времени и т.д., это не должно быть проблемой для большинства приложений.

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

16
ответ дан 1 December 2019 в 06:12
поделиться
sb.setLength(0);
sb.append("testString");
23
ответ дан 1 December 2019 в 06:12
поделиться

Вы можете использовать StringBuilder вместо StringBuffer , что обычно и делают люди, если могут ( StringBuilder не синхронизируется, поэтому он быстрее, но не безопасен). Если вам нужно инициализировать содержимое одного файла другим, используйте метод toString () для получения строкового представления. Чтобы повторно использовать существующий StringBuilder или StringBuffer , просто вызовите setLength (0) .

Редактировать
Вы можете перезаписать ряд элементов с помощью функции replace () . Чтобы изменить все значение на newval , вы должны использовать buffer.replace (0, buffer.length (), newval) . См. Также:

3
ответ дан 1 December 2019 в 06:12
поделиться

Возможно, вы ищете метод 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");
2
ответ дан 1 December 2019 в 06:12
поделиться

Вы можете преобразовать в / из 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
0
ответ дан 1 December 2019 в 06:12
поделиться

Что вы имеете в виду под словом «переназначить»? Вы можете очистить содержимое, используя setLength () , а затем начать добавлять новое содержимое, если вы это имеете в виду.

Изменить : для изменения частей содержимого вы можете использовать replace () .

Как правило, на этот вопрос можно легко ответить, просмотрев документацию по API соответствующих классов.

8
ответ дан 1 December 2019 в 06:12
поделиться

В самом деле, я думаю, что 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;
  }
1
ответ дан 1 December 2019 в 06:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: