Как переназначить значение StringBuffer?

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

StringBuffer sb=new StringBuffer("teststr");

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

Ответы

Ответ 1

Вначале следует упомянуть, что StringBuilder обычно предпочтительнее StringBuffer. Из StringBuffer собственный API:

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

Но вместо этого я буду использовать replace(CharSequence, CharSequence) из String. В большинстве случаев это будет более чем достаточно, и это определенно намного понятнее и проще в обслуживании. Он линейный по длине входной строки, поэтому он асимптотически оптимален.

String before = "str1str2str3";
String after = before.replace("str", "String");
assert after.equals("String1String2String3");

Обсуждение

"Я ищу метод для назначения значения позже, используя предыдущую ячейку памяти"

Точная ячейка памяти не должна быть для вас проблемой; на самом деле, как StringBuilder, так и StringBuffer будут перераспределять свой внутренний буфер в разные ячейки памяти, когда это необходимо. Единственный способ предотвратить это будет ensureCapacity (или установить его через конструктор), чтобы его внутренний буфер всегда был достаточно большим, и его никогда не нужно было перераспределять.

Однако даже если StringBuffer перераспределяет свой внутренний буфер раз в то время, это не должно быть проблемой в большинстве случаев. Большинство структур данных, которые динамически растут (ArrayList, HashMap и т.д.), Делают их таким образом, чтобы сохранить алгоритмически оптимальные операции, используя амортизацию затрат. Я не буду анализировать амортизацию здесь, но если вы не используете системы реального времени и т.д., Это не должно быть проблемой для большинства приложений.

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

Ответ 2

sb.setLength(0);
sb.append("testString");

Ответ 3

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

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

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

Ответ 4

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

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

Ответ 5

Возможно, вы ищете метод 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");

Ответ 6

В самом деле, я думаю, replace() - лучший способ. Я проверил код Java-Source. Это действительно перезаписывает старые символы.

Вот исходный код 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;
  }

Ответ 7

Вы можете преобразовать в/из строки, как показано ниже:

 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

Ответ 8

Изменение всего значения StringBuffer:

  StringBuffer sb = new StringBuffer("word");
  sb.setLength(0); // setting its length to 0 for making the object empty
  sb.append("text");

Вот как вы можете изменить все значение StringBuffer.