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

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

StringBuffer sb=new StringBuffer("teststr");

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

8 ответов


прежде всего следует упомянуть, что StringBuilder обычно предпочтительнее StringBuffer. От StringBufferсобственный API:

начиная с выпуска JDK 5, Этот класс был дополнен эквивалентным классом, предназначенным для использования одним потоком, StringBuilder. The StringBuilder класс обычно следует использовать в предпочтении к этому, так как он поддерживает все те же операции, но он быстрее, так как он не выполняет синхронизацию.

что сказал, я будет придерживаться StringBuffer для остальной части ответа, потому что это то, что вы спрашиваете; все, что StringBuffer нет, StringBuilder также... кроме синхронизации, которая обычно не нужна. Поэтому, если вы не используете буфер в нескольких потоках, переключитесь на StringBuilder - это простая задача.


вопрос

StringBuffer sb = new StringBuffer("teststr");

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

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

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

обсуждения

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

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

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

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


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

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

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

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


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

редактировать
Вы можете перезаписать диапазон элементов с помощью


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

действительно, я думаю 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;
  }

вы можете конвертировать в/из строки следующим образом:

 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

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

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

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