为啥 StringBuffer/StringBuilder 不覆盖 equals 或 hashCode?

Posted

技术标签:

【中文标题】为啥 StringBuffer/StringBuilder 不覆盖 equals 或 hashCode?【英文标题】:Why does StringBuffer/StringBuilder not override equals or hashCode?为什么 StringBuffer/StringBuilder 不覆盖 equals 或 hashCode? 【发布时间】:2012-06-22 04:17:58 【问题描述】:

为什么 StringBuffer/StringBuilder 不覆盖对象中的equals()hashcode() 方法?

请给我建议清晰的图片,以帮助理解问题...

【问题讨论】:

【参考方案1】:

因为StringBuffer 是可变的,它的主要用途是构造 字符串。如果要比较内容,调用StringBuffer#toString(),比较返回值。

对于可变对象覆盖hashCode() 通常没有用处,因为修改用作HashMap 中的键的此类对象可能会导致存储的值“丢失”。

【讨论】:

这里的可变是什么意思? 如果您不了解非常基本的原理,请进行一些研究:***.com/questions/3554192/… 恕我直言,我不同意你的说法为可变对象覆盖 hashCode() 通常没有用... @Shahzeb 举例说明何时可以使用可变对象的 hashCode() 对我来说,第一个明显的参考点是任何 ORM 类,所以这里是来自 hibernate 的链接以及在 SO ***.com/questions/5031614/… 的长时间讨论【参考方案2】:

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

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

这两个值都将被添加到 hashMap 中,因为 sb1 和 sb2 都返回不同的哈希码。 StringBuilder/StringBuffer 不会覆盖 equals() 和 hashCode() 方法。

Sun Microsystem 希望程序员允许在 Hashtable 或任何其他 Hash 集合(HashSet、HashMap...)中添加 2 种不同的 String 类型的值,这就是 hashCode() 和 equals() 没有被有意覆盖的原因StringBuffer,StringBuilder 类。

【讨论】:

Sun Microsystem wanted the programmer to allow adding 2 different String kind of Values in Hashtable ... 这不是真的,HashtableMap 的 javadocs 积极反对使用带有损坏的 equals/hashcode 合约的对象作为键。将 StringBuilder 对象存储在地图中没有用处,因为除非您拥有原始对象,否则您将无法通过键获取值。【参考方案3】:

因为 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,但没有说明原因。答案本身 (Because StringBuffer is mutable) 是从之前的答案中复制而来的。

以上是关于为啥 StringBuffer/StringBuilder 不覆盖 equals 或 hashCode?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 DataGridView 上的 DoubleBuffered 属性默认为 false,为啥它受到保护?

为啥需要softmax函数?为啥不简单归一化?

为啥 g++ 需要 libstdc++.a?为啥不是默认值?

为啥或为啥不在 C++ 中使用 memset? [关闭]

为啥临时变量需要更改数组元素以及为啥需要在最后取消设置?

为啥 CAP 定理中的 RDBMS 分区不能容忍,为啥它可用?