如何重新分配StringBuffer的值?

Bij*_* CD 14 java string stringbuilder stringbuffer

我们如何重新赋值StringBuffer或StringBuilder变量的值?

StringBuffer sb=new StringBuffer("teststr");
Run Code Online (Sandbox Code Playgroud)

现在我必须将sb的值更改为"testString"而不清空内容.我正在寻找一种方法,可以直接执行此分配,而无需使用单独的内存分配.我认为我们只能在清空内容后才能执行此操作.

web*_*key 23

sb.setLength(0);
sb.append("testString");
Run Code Online (Sandbox Code Playgroud)

  • 比顶部的高投票小说更好的答案:) (6认同)

pol*_*nts 16

首先应该提到StringBuilder通常优选的StringBuffer.来自StringBuffer自己的API:

从JDK 5发行版开始,这个类已经补充了一个设计用于单个线程的等效类StringBuilder.所述StringBuilder类通常应优先使用这一个,因为它支持所有相同的操作,但它是快的,因为它不执行同步.

也就是说,我会坚持StringBuffer回答其余部分,因为那就是你所要求的; 所做的一切StringBuffer,StringBuilder也......除了同步,这通常是不需要的.因此,除非您在多个线程中使用缓冲区,否则切换到这StringBuilder是一项简单的任务.


这个问题

StringBuffer sb = new StringBuffer("teststr");
Run Code Online (Sandbox Code Playgroud)

"现在我要改变的值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");
Run Code Online (Sandbox Code Playgroud)

这不必要地覆盖"tr""tr".

StringBuffer sb = new StringBuffer("teststr");
sb.replace(4, sb.length(), "String");
assert sb.toString().equals("testString");
Run Code Online (Sandbox Code Playgroud)

这包括由于deleteCharAt和的转变insert.

StringBuffer sb = new StringBuffer("teststr");
sb.deleteCharAt(4);
sb.insert(4, 'S');
sb.append("ing");
assert sb.toString().equals("testString");
Run Code Online (Sandbox Code Playgroud)

现在这有点不同了:它并不神奇地知道"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");
Run Code Online (Sandbox Code Playgroud)

现在假设您要替换所有出现的"str"并将其替换为"String".A StringBuffer没有内置的此功能.您可以尝试以最有效的方式自行完成,就地(可能使用2遍算法)或使用秒StringBuffer等.

但相反,我将使用replace(CharSequence, CharSequence)String.在大多数情况下,这将是非常好的,并且肯定更清晰,更容易维护.它在输入字符串的长度上是线性的,因此它是渐近最优的.

String before = "str1str2str3";
String after = before.replace("str", "String");
assert after.equals("String1String2String3");
Run Code Online (Sandbox Code Playgroud)

讨论

"我正在寻找以后通过使用以前的内存位置来分配值的方法"

准确的记忆位置不应该是你真正关心的问题; 实际上,无论是StringBuilderStringBuffer将重新分配其内部缓冲区到不同的存储位置在必要时.防止这种情况的唯一方法是ensureCapacity(或通过构造函数设置),以便其内部缓冲区总是足够大,并且永远不需要重新分配.

但是,即使偶尔StringBuffer重新分配其内部缓冲区,在大多数情况下也不应该成为问题.大多数动态增长的数据结构(ArrayList,HashMap等)以保持算法优化操作的方式执行它们,利用成本摊销.我不会在这里进行摊销分析,但除非您正在进行实时系统等,否则对于大多数应用程序来说这不应该是一个问题.

显然我并不知道你需要的具体细节,但是因为你似乎担心大多数人都不必担心的事情,所以担心会过早优化.


Mic*_*rdt 8

"重新分配"是什么意思?setLength()如果这是你的意思,你可以通过使用然后开始追加新内容来清空内容.

编辑:要更改内容的部分,您可以使用replace().

通常,通过查看相关类的API文档可以轻松回答这类问题.