关于字符串反转的问题

发布于 2024-09-12 06:48:20 字数 356 浏览 1 评论 0原文

我正在尝试进行简单的字符串操作。输入是“murder”,我想得到“murderredrum”。

我尝试过这个

String str = "murder";
StringBuffer buf = new StringBuffer(str);
// buf is now "murder", so i append the reverse which is "redrum"
buf.append(buf.reverse());
System.out.println(buf);

,但现在我得到“redrumredrum”而不是“murderredrum”。

有人可以解释我的程序出了什么问题吗?谢谢。

i am trying to do a simple string manipulation. input is "murder", i want to get "murderredrum".

i tried this

String str = "murder";
StringBuffer buf = new StringBuffer(str);
// buf is now "murder", so i append the reverse which is "redrum"
buf.append(buf.reverse());
System.out.println(buf);

but now i get "redrumredrum" instead of "murderredrum".

can someone explain what's wrong with my program? thank you.

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

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

发布评论

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

评论(2

划一舟意中人 2024-09-19 06:48:20

简短的回答

该行:

buf.append(buf.reverse());

本质上执行以下操作:

buf.reverse();    // buf is now "redrum"
buf.append(buf);

这就是您得到“redrumredrum”的原因。

也就是说,buf.reverse() 不会返回与 buf 相反的新 StringBuffer。它在反转后返回 buf

有很多方法可以“修复”此问题,但最简单的方法是显式创建一个新的 StringBuffer 来进行反转,因此如下所示:

buf.append(new StringBuffer(str).reverse());

更深入的见解:比较 String 和 Java 中的StringBuffer

String不可变的。另一方面,StringBuffer可变的(这就是为什么您可以向其中追加 内容等)。

这就是为什么使用 String 时,转换方法实际上返回一个new String。这就是为什么这样的事情是“错误的”,

String str = "murder";
str.toUpperCase(); // this is "wrong"!!!
System.out.println(str); // still "murder"

而您却想要这样做:

String str = "murder";
str = str.toUpperCase(); // YES!!!
System.out.println(str); // now "MURDER"!!!

但是,情况与 StringBuffer 相差甚远。大多数StringBuffer方法确实返回StringBuffer,但它们返回与调用它的实例相同!它们返回一个新的StringBuffer实例。事实上,您可以随意丢弃“结果”,因为这些方法已经通过对其调用的实例进行各种突变(即副作用)来完成它们所做的事情。

这些方法可以被声明为void,但它们本质上返回this;的原因是因为它有助于方法链接,允许您编写类似以下内容:

sb.append(thisThing).append(thatThing).append(oneMoreForGoodMeasure);

相关问题


附录:StringBufferStringBuilder

而不是StringBuffer,您通常应该更喜欢 StringBuilder,它更快,因为它不是同步。上面的大部分讨论也适用于StringBuilder

从文档中:

StringBuffer线程安全、可变的字符序列。 [...] 从 JDK 5 开始,此类已补充了一个为单线程使用而设计的等效类 StringBuilder,通常应首选该类,因为它支持所有相同的操作,但速度更快,因为它不执行同步。

StringBuilder< /a> :可变的字符序列。 [...] StringBuilder 的实例对于多线程使用是不安全的。如果需要这样的同步,那么建议使用StringBuffer


相关问题


额外材料!替代解决方案!

这是问题的替代“修复”,可能更具可读性:

StringBuilder word = new StringBuilder("murder");
StringBuilder worddrow = new StringBuilder(); // starts empty

worddrow.append(word).append(word.reverse());

System.out.println(worddrow); // "murderredrum"

请注意,虽然这对于短字符串应该很好,但它确实使用了额外的缓冲区,这意味着它不是解决问题的最有效方法。

相关问题


又是福利材料!笑到最后!

StringBuilder sb = new StringBuilder("ha");
sb.append(sb.append(sb));
System.out.println(sb); // "hahahaha"

The short answer

The line:

buf.append(buf.reverse());

essentially does the following:

buf.reverse();    // buf is now "redrum"
buf.append(buf);

This is why you get "redrumredrum".

That is, buf.reverse() doesn't return a new StringBuffer which is the reverse of buf. It returns buf, after it had reversed itself!

There are many ways to "fix" this, but the easiest would be to explicitly create a new StringBuffer for the reversal, so something like this:

buf.append(new StringBuffer(str).reverse());

Deeper insight: comparing String and StringBuffer

String in Java is immutable. On the other hand, StringBuffer is mutable (which is why you can, among other things, append things to it).

This is why with String, a transforming method really returns a new String. This is why something like this is "wrong"

String str = "murder";
str.toUpperCase(); // this is "wrong"!!!
System.out.println(str); // still "murder"

Instead you want to do:

String str = "murder";
str = str.toUpperCase(); // YES!!!
System.out.println(str); // now "MURDER"!!!

However, the situation is far from analogous with StringBuffer. Most StringBuffer methods do return StringBuffer, but they return the same instance that it was invoked on! They do NOT return a new StringBuffer instance. In fact, you're free to discard the "result", because these methods have already accomplished what they do through various mutations (i.e. side effects) to the instance it's invoked upon.

These methods could've been declared as void, but the reason why they essentially return this; instead is because it facilitates method chaining, allowing you to write something like:

sb.append(thisThing).append(thatThing).append(oneMoreForGoodMeasure);

Related questions


Appendix: StringBuffer vs StringBuilder

Instead of StringBuffer, you should generally prefer StringBuilder, which is faster because it's not synchronized. Most of the discussions above also applies to StringBuilder.

From the documentation:

StringBuffer : A thread-safe, mutable sequence of characters. [...] As of JDK 5, this class has been supplemented with an equivalent class designed for use by a single thread, StringBuilder, which should generally be preferred as it supports all of the same operations but faster, as it performs no synchronization.

StringBuilder : A mutable sequence of characters. [...] Instances of StringBuilder are not safe for use by multiple threads. If such synchronization is required then it is recommended that StringBuffer be used.

Related questions


Bonus material! Alternative solution!

Here's an alternative "fix" to the problem that is perhaps more readable:

StringBuilder word = new StringBuilder("murder");
StringBuilder worddrow = new StringBuilder(); // starts empty

worddrow.append(word).append(word.reverse());

System.out.println(worddrow); // "murderredrum"

Note that while this should do fine for short strings, it does use an extra buffer which means that it's not the most efficient way to solve the problem.

Related questions


Bonus material again! The last laugh!

StringBuilder sb = new StringBuilder("ha");
sb.append(sb.append(sb));
System.out.println(sb); // "hahahaha"
为人所爱 2024-09-19 06:48:20

buf.reverse() 首先被调用,它将字符串缓冲区修改为 redrum。现在您正在将 redrum 附加到 redrum

buf.reverse() gets called first it modifies the stringbuffer to redrum. Now you are appending redrum to redrum

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