【问题标题】:Question about reversing a string关于反转字符串的问题
【发布时间】:2010-07-31 20:24:04
【问题描述】:

我正在尝试做一个简单的字符串操作。输入是“谋杀”,我想得到“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”。

谁能解释我的程序有什么问题?谢谢。

【问题讨论】:

    标签: java string reverse


    【解决方案1】:

    简短的回答

    行:

    buf.append(buf.reverse());
    

    主要做以下事情:

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

    这就是你得到"redrumredrum"的原因。

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

    有很多方法可以“解决”这个问题,但最简单的方法是显式创建一个新的StringBuffer 以进行逆转,所以是这样的:

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

    更深入的了解:比较 StringStringBuffer

    String 在 Java 中是不可变的。另一方面,StringBuffer可变的(这就是为什么你可以,除其他外,append 事情)。

    这就是为什么使用String,转换方法真正返回一个 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,但它们本质上是return this;的原因是因为它促进了method chaining,允许您编写如下内容:

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

    相关问题


    附录:StringBuffer vs StringBuilder

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

    来自文档:

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

    StringBuilder :可变的字符序列。 [...] 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"
    

    【讨论】:

    • +1,StringBuffer 是可变的。这可能是 OP 的困惑,因为像 reverse() 这样的方法返回一个 StringBuffer,有点像 String 的方法。但他们确实改变了实例并返回实例只是为了方便链接。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2020-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-23
      • 1970-01-01
      • 2020-07-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多