为什么StringBuffer/StringBuilder没有重写equals或hashCode方法?

31
为什么StringBuffer/StringBuilder没有覆盖Object类的equals()和hashcode()方法?请给出一个清晰的解释,帮助读者理解这个问题。
3个回答

42
因为 StringBuffer 是可变的,其主要用途是用于构建字符串。如果你想比较内容,请调用 StringBuffer#toString() 并比较返回的值。
对于可变对象,通常没有必要覆盖 hashCode(),因为修改在 HashMap 中用作键的此类对象可能会导致存储的值“丢失”。

这里的Mutable是什么意思? - Saravanan
6
如果您不理解基本的原则,请进行一些研究:https://dev59.com/u0_Ta4cB1Zd3GeqPFf3s - Matt Ball
2
恕我直言,我不同意你的说法:“对于可变对象来说,重写hashCode()方法通常是没有用的……” - Shahzeb
1
@Shahzeb,能否举个例子说明可变对象的hashCode()何时会被使用? - Matt Ball
1
我最明显的参考点是任何ORM类,这里有一个来自hibernate的链接和一个在SO上的长讨论https://dev59.com/Fm445IYBdhLWcg3wGmo6。 - Shahzeb
显示剩余3条评论

8

实际上,这一切都取决于哈希码的值。为了理解这个概念,让我们举个例子:

String str1 = new String("sunil");
String str2 = new String("sunil");

HashMap hm = new HashMap()
hm.put(str1,"hello");
hm.put(str2,"bye");

最终的哈希表:

hm = { sunil=bye }

在上面的代码中,str1和str2是两个不同的String对象。它们应该分别添加到HashMap中吗?答案是不需要。这是因为在将值插入/放入HashMap之前,它会在内部检查和比较str1str2的hashCode值。由于String类重写了equals()和hashcode()方法,因此两者返回相同的哈希码值。因此,在执行hm.put(str2,"bye");时,第一个键将被新值覆盖。现在试试这个:
StringBuilder sb1 = new StringBuilder("sunil");
StringBuilder sb2 = new StringBuilder("sunil");

HashMap hm = new HashMap()
hm.put(sb1,"hello");//sb1 and sb2 will return different HashCode 
hm.put(sb2,"bye");// StringBuffer/StringBuilder does not override hashCode/equals methods

最终的哈希映射:
{sunil=hello, sunil=bye}

因为sb1和sb2返回不同的hashcode,所以两个值都将被添加到hashMap中。StringBuilder/ StringBuffer没有重写equals()和hashCode()方法。

Sun Microsystems希望程序员允许在Hashtable或任何其他哈希集合(如HashSet、HashMap等)中添加2种不同类型的字符串值,这就是为什么StringBuffer、StringBuilder类没有故意覆盖hashCode()和equals()的原因。


2
Sun Microsystems 希望程序员允许在 Hashtable 中添加 2 种不同的 String 类型值... 这是不正确的,HashtableMap 的 javadocs 明确禁止使用具有破损的 equals/hashcode 合同的对象作为键。将 StringBuilder 对象存储在映射中没有用处,因为除非您拥有原始对象,否则无法通过键获取值。 - default locale

-1

因为StringBuffer是可变的。附带示例尝试一下:)

package test;

import java.util.HashMap;

public class CheckHashcodeEquals {

    public static void main(String[] args) {

        /*
         * String class override equals() and hashcode() method thats way
         * override value of HashMap
         */
        String s1 = new String("Arya");
        String s2 = new String("Arya");
        HashMap hm = new HashMap<>();
        hm.put(s1, "A1");
        hm.put(s2, "A2");
        System.out.println(hm); /* Output: {Arya=A2} */

        /*
         * String class does not override equals() and hashcode() method thats
         * way insert duplicate value
         */
        StringBuffer sb1 = new StringBuffer("Arya");
        StringBuffer sb2 = new StringBuffer("Arya");
        HashMap hm2 = new HashMap<>();
        hm2.put(sb1, "A1");
        hm2.put(sb2, "A2");
        System.out.println(hm2); /* Output: {Arya=A2, Arya=A1} */
    }

}

这个例子展示了StringBuffer没有重写equalshashcode方法,但是并没有说明原因。答案本身(因为StringBuffer是可变的)是从早期的回答中复制过来的。 - default locale

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接