如何重新分配StringBuffer的值?

发布于 2024-08-27 14:16:47 字数 218 浏览 14 评论 0原文

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

StringBuffer sb=new StringBuffer("teststr");

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

How can we re assign the value of a StringBuffer or StringBuilder Variable?

StringBuffer sb=new StringBuffer("teststr");

Now i have to change the value of sb to "testString" without emptying the contents.
I am looking at a method which can do this assignment directly without using separate memory allocation.I think we can do it only after emptying the contents.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

梦罢 2024-09-03 14:16:47
sb.setLength(0);
sb.append("testString");
sb.setLength(0);
sb.append("testString");
段念尘 2024-09-03 14:16:47

首先应该提到的是,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");

这涉及由于 deleteCharAtinsert 导致的转变。

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

现在有点不同了:它并不神奇地知道它有需要编辑为 "testString""teststr" ;它仅假设 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 等。

但我将使用 字符串替换(CharSequence, CharSequence)。在大多数情况下,这已经足够好了,而且绝对更清晰、更容易维护。它与输入字符串的长度呈线性关系,因此它是渐近最优的。

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

讨论

“我正在寻找稍后使用以前的内存位置赋值的方法”

确切的内存位置不应该真正成为您关心的问题;事实上,StringBuilderStringBuffer 都会在必要时将其内部缓冲区重新分配到不同的内存位置。防止这种情况的唯一方法是ensureCapacity(或通过构造函数设置它),以便其内部缓冲区始终足够大,并且永远不需要重新分配。

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

显然,我不知道您的具体需求,但担心过早优化,因为您似乎担心大多数人永远不必担心的事情。

It should first be mentioned that StringBuilder is generally preferred to StringBuffer. From StringBuffer's own API:

As of release JDK 5, this class has been supplemented with an equivalent class designed for use by a single thread, StringBuilder. The StringBuilder class should generally be used in preference to this one, as it supports all of the same operations but it is faster, as it performs no synchronization.

That said, I will stick to StringBuffer for the rest of the answer because that's what you're asking; everything that StringBuffer does, StringBuilder also... except synchronization, which is generally unneeded. So unless you're using the buffer in multiple threads, switching to StringBuilder is a simple task.


The question

StringBuffer sb = new StringBuffer("teststr");

"Now i have to change the value of sb to "testString" without emptying the contents"

So you want sb to have the String value "testString" in its buffer? There are many ways to do this, and I will list some of them to illustrate how to use the API.


The optimal solution: it performs the minimum edit from "teststr" to "testString". It's impossible to do it any faster than this.

StringBuffer sb = new StringBuffer("teststr");
sb.setCharAt(4, 'S');
sb.append("ing");
assert sb.toString().equals("testString");

This needlessly overwrites "tr" with "tr".

StringBuffer sb = new StringBuffer("teststr");
sb.replace(4, sb.length(), "String");
assert sb.toString().equals("testString");

This involves shifts due to deleteCharAt and insert.

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

This is a bit different now: it doesn't magically know that it has "teststr" that it needs to edit to "testString"; it assumes only that the StringBuffer contains at least one occurrence of "str" somewhere, and that it needs to be replaced by "String".

StringBuffer sb = new StringBuffer("strtest");
int idx = sb.indexOf("str");
sb.replace(idx, idx + 3, "String");
assert sb.toString().equals("Stringtest");

Let's say now that you want to replace ALL occurrences of "str" and replace it with "String". A StringBuffer doesn't have this functionality built-in. You can try to do it yourself in the most efficient way possible, either in-place (probably with a 2-pass algorithm) or using a second StringBuffer, etc.

But instead I will use the replace(CharSequence, CharSequence) from String. This will be more than good enough in most cases, and is definitely a lot more clear and easier to maintain. It's linear in the length of the input string, so it's asymptotically optimal.

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

Discussions

"I am looking for the method to assign value later by using previous memory location"

The exact memory location shouldn't really be a concern for you; in fact, both StringBuilder and StringBuffer will reallocate its internal buffer to different memory locations whenever necessary. The only way to prevent that would be to ensureCapacity (or set it through the constructor) so that its internal buffer will always be big enough and it would never need to be reallocated.

However, even if StringBuffer does reallocate its internal buffer once in a while, it should not be a problem in most cases. Most data structures that dynamically grows (ArrayList, HashMap, etc) do them in a way that preserves algorithmically optimal operations, taking advantage of cost amortization. I will not go through amortized analysis here, but unless you're doing real-time systems etc, this shouldn't be a problem for most applications.

Obviously I'm not aware of the specifics of your need, but there is a fear of premature optimization since you seem to be worrying about things that most people have the luxury of never having to worry about.

灼疼热情 2024-09-03 14:16:47

“重新分配”是什么意思?您可以使用 < 清空内容code>setLength() 然后开始附加新内容(如果这就是您的意思)。

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

一般来说,这种问题可以通过查看相关类的 API 文档来轻松回答。

What do you mean with "reassign"? You can empty the contents by using setLength() and then start appending new content, if that's what you mean.

Edit: For changing parts of the content, you can use replace().

Generally, this kind of question can be easily answered by looking at the API doc of the classes in question.

方圜几里 2024-09-03 14:16:47

您可以使用 StringBuilder 代替 StringBuffer,如果可以的话,这通常是人们所做的事情(StringBuilder 不同步,因此它是更快但不是线程安全的)。如果您需要用另一个来初始化一个的内容,请使用 toString() 方法来获取字符串表示形式。要回收现有的 StringBuilderStringBuffer,只需调用 setLength(0) 即可。

编辑
您可以使用 replace() 函数覆盖一系列元素。要将整个值更改为 newval,您可以使用 buffer.replace(0,buffer.length(),newval)。另请参阅:

You can use a StringBuilder in place of a StringBuffer, which is typically what people do if they can (StringBuilder isn't synchronized so it is faster but not threadsafe). If you need to initialize the contents of one with the other, use the toString() method to get the string representation. To recycle an existing StringBuilder or StringBuffer, simply call setLength(0).

Edit
You can overwrite a range of elements with the replace() function. To change the entire value to newval, you would use buffer.replace(0,buffer.length(),newval). See also:

喜爱纠缠 2024-09-03 14:16:47

您可能正在寻找 StringBuffer 的 Replace() 方法:

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");

You might be looking for the replace() method of the StringBuffer:

StringBuffer sb=new StringBuffer("teststr");
sb.replace(0, sb.length() - 1, "newstr");

Internally, it removes the original string, then inserts the new string, but it may save you a step from this:

StringBuffer sb=new StringBuffer("teststr");
sb.delete(0, sb.length() - 1);
sb.append("newstr");

Using setLength(0) reassigns a zero length StringBuffer to the variable, which, I guess, is not what you want:

StringBuffer sb=new StringBuffer("teststr");
// Reassign sb to a new, empty StringBuffer
sb.setLength(0);
sb.append("newstr");
俏︾媚 2024-09-03 14:16:47

事实上,我认为 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;
  }

Indeed, I think replace() is the best way. I checked the Java-Source code. It really overwrites the old characters.

Here is the source code from 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;
  }
烟─花易冷 2024-09-03 14:16:47

更改 StringBuffer 的整个值:

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

这是更改 StringBuffer 的整个值的方法。

Changing entire value of StringBuffer:

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

This is how you can change the entire value of StringBuffer.

七度光 2024-09-03 14:16:47

您可以与字符串进行转换,如下所示:

 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

You can convert to/from a String, as follows:

 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文