【问题标题】:Why equals() is true after using StringBuffer.reverse?为什么使用 StringBuffer.reverse 后 equals() 为真?
【发布时间】:2014-06-19 17:31:15
【问题描述】:

p.equals(w) 总是会成真。为什么?

http://ideone.com/JqLCDi

    import java.io.*;
import java.util.Scanner;

class TestClass {
    public static void main(String args[] ) throws Exception {

       Scanner s=new Scanner(System.in);
       int t=s.nextInt();
       while(t-->0){
        String k=s.next();
       StringBuffer p=new StringBuffer(k);
       int c=0;

       StringBuffer w=p.reverse();

       if(p.equals(w)){
        System.out.print(p.equals(w));

       for(int i=0;i<p.length();i++)
       {
        if(p.charAt(i)=='1'||p.charAt(i)=='0'||p.charAt(i)=='8') { c++;}
       }
       }
       if(c==p.length())System.out.println("YES");
        else System.out.println("NO");

}

    }
}

【问题讨论】:

  • 你为什么不用equalsIgnoreCase()
  • 即使是正确复制的 (!) 和反转的缓冲区也总是比较不相等,因为 StringBuffer 不会覆盖等于。

标签: java equals reverse stringbuilder stringbuffer


【解决方案1】:
public synchronized StringBuffer reverse() {
super.reverse();
return this;
}

Reverse 将反转字符串并将其设置在同一个 StringBuffer 对象中。所以它永远都是一样的。

所以

p.reverse();

做和说一样的事情

p = p.reverse();

如果你这样做了

StringBuffer w=p.reverse();

pw 将指向同一个对象。不用说equals() 将返回true

您可以在StringBuffer 的反向操作之前和之后存储字符串对象,然后对它们使用equals()。 toString() 返回新的字符串对象。

public synchronized String toString() {
return new String(value, 0, count);
}

【讨论】:

  • 好收获。 +1 现在你只需要解决方案.. :)
  • 是的,我只是在输入解决方案 :)
【解决方案2】:

不同于String,StringBuffer1是一个可变类型。忠实于这个设计,StringBuffer.reverse修改原始对象,然后返回same(当前)StringBuffer实例;返回相同的实例允许方法链接:

[reverse] 使这个字符序列被序列的反向替换[并返回] 对这个 [StringBuffer] 对象的引用。

这样

StringBuffer w=p.reverse();

在语义上等价于

p.reverse();          // side-effect! reverses content
StringBuffer w == p;
// w == p -> true (same object), implies w.equals(p) -> true

解决此问题的一种方法是为 w 创建一个 new StringBuffer 实例,然后反向。

StringBuffer w = new StringBuffer(p);
// w == p -> false, w.equals(p) -> true
p.reverse();
// w == p -> false, w.equals(p) -> false

如果只需要一个字符串,则应用相同的规则/逻辑 - 在反转 StringBuffer 之前创建数据的新对象/副本

String s = p.toString()
// s == p -> false, s.equals(p) -> true
p.reverse();
// s == p -> false, s.equals(p) -> false

虽然我怀疑这是实际任务,但请考虑p.toString.equals(p.reverse()),它也遵循前面的逻辑。

boolean reversed = p.toString()    // "s", new String / data copy
                    .equals(
                       p.reverse() // "p", reverse done after copy
                     );

1 StringBuffer 是旧的,除非需要同步属性,否则继续使用StringBuilder

[StringBuilder] 被设计为在字符串缓冲区被单线程使用的地方用作 StringBuffer 的替代品。在可能的情况下,建议优先使用此类而不是 StringBuffer,因为它在大多数实现下会更快。

【讨论】:

  • 更简单:只需使用String current = p.toString(); String reversedContent = p.reverse().toString(); /* compare current against reversedContent */
  • @LuiggiMendoza 谢谢,我已经包含了使用 toString 而不是创建新 SB 的案例。
【解决方案3】:

在你的 if 条件中使用它

if(p.toString().equals(p.reverse().toString()))

【讨论】:

  • 如果您使用StringBuffer#reverse,这将不起作用,因为它们都将具有相同的内容...
猜你喜欢
  • 1970-01-01
  • 2011-09-12
  • 1970-01-01
  • 2015-02-12
  • 2010-11-09
  • 2010-09-25
  • 1970-01-01
  • 2015-03-17
  • 2013-09-05
相关资源
最近更新 更多