我们如何重新赋值StringBuffer或StringBuilder变量的值?
StringBuffer sb=new StringBuffer("teststr");
现在我必须将sb的值更改为“testString”而不清空内容。 我正在研究一种方法,它可以直接执行此分配而无需使用单独的内存分配。我认为只有在清空内容后才能执行此操作。
答案 0 :(得分:21)
sb.setLength(0);
sb.append("testString");
答案 1 :(得分:16)
首先应该提到StringBuilder
通常优先于StringBuffer
。来自StringBuffer
's own 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");
现在假设您要替换{em>所有次"str"
次出现并将其替换为"String"
。 StringBuffer
没有内置此功能。您可以尝试以最有效的方式自行完成,就地(可能使用2遍算法)或使用第二个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 :(得分:8)
“重新分配”是什么意思?您可以使用setLength()
清空内容,然后开始添加新内容,如果这就是您的意思。
修改:要更改部分内容,您可以使用replace()
。
通常,通过查看相关课程的API文档可以轻松回答这类问题。
答案 3 :(得分:3)
您可以使用StringBuilder
代替StringBuffer
,这通常是人们可以做的事情(StringBuilder
未同步,因此它更快但不是线程安全的)。如果需要使用另一个来初始化one的内容,请使用toString()
方法获取字符串表示。要回收现有的StringBuilder
或StringBuffer
,只需致电setLength(0)
。
修改的
您可以使用replace()
函数覆盖一系列元素。要将整个值更改为newval
,您可以使用buffer.replace(0,buffer.length(),newval)
。另见:
答案 4 :(得分:2)
您可能正在寻找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");
答案 5 :(得分:1)
的确,我认为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;
}
答案 6 :(得分:0)
您可以转换为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
答案 7 :(得分:-1)
更改StringBuffer的整个值:
StringBuffer sb = new StringBuffer("word");
sb.setLength(0); // setting its length to 0 for making the object empty
sb.append("text");
这是你可以改变StringBuffer的整个值的方法。