为什么String对象的hashCode()与自定义类'对象的hashCode()不同?

时间:2012-03-30 14:51:22

标签: java

为什么stringObject的哈希码是我提供的字符串?

String s = new String(); // here the hascode is 0. 

但是当我得到我创建的某个对象的哈希码时。

testClass o = new testClass(); // the hashcode is some random number.

我的问题是两者有什么区别?我的理解是hashCode()来自Object班,这是所有班级的母亲。

7 个答案:

答案 0 :(得分:7)

  

为什么stringObject的哈希码是我提供的字符串?   恩。 String s = new String(“hello”); //这里的hascode是你好的。

那不是真的

hashCode()是一个int数

您似乎将hashcode()与toString()

混淆

如果您想查看hashcode()

String str = "hello";
System.out.println(str.hashcode());//will print some int number
System.out.println(str);//will invoke toString() which will return `hello`

答案 1 :(得分:0)

我认为您将hashCode()toString()混为一谈。

每个对象的默认toString()实现确实是<classname>@<some number>,并且该数字恰好是十六进制中对象的哈希码,但是可以(并且应该)被可以提供的类覆盖更有意义的字符串表示。对于字符串,明显的字符串表示本身就是。

答案 2 :(得分:0)

String s = new String(“hello”); 这个哈希码永远不会是 Hello ,因为 hashCode()方法会返回type是 int 而不是字符串

答案 3 :(得分:0)

String是Java库中提供的类。因此,hashCode()方法已被此类的创建者覆盖以反映它。请注意,哈希码是一个int值。

当您创建一个类时,您希望覆盖hashCode()equals()方法,以便能够比较您的对象,并做其他很酷的事情(将它们放在{{1例如)。

您需要注意如何实现HashMap,因为您希望尊重一般合同,即根据hashCode()方法,如果两个对象相等,则它们具有相同的{{1} 1}},而相反的情况不一定是真的(但建议)。

您可以在此处找到更深入的解释 - http://www.javaworld.com/community/node/1006

答案 4 :(得分:0)

这里有一些问题:

  1. 正如其他人已经说过的那样 - hashCode()会返回一个整数,您可能会对toString()
  2. 感到困惑
  3. 哪个更重要IMO:Object同时包含hashCode()toString()方法。但是,Object的任何子类都可以override这种方法。当调用该方法时 - 将调用动态类型的方法,因此对于String,将调用String.hashCode()而不是Object.hashCode() [{1}}的相同想法]。这称为dynamic dispatch
  4. 例如:

    toString()

    在上面的代码快照中,系统会调用public static class A { public void foo() { System.out.println("A"); } } public static class B extends A{ @Override public void foo() { System.out.println("B"); } } public static void main(String[] args) throws Exception { A a = new B(); a.foo(); } ,并会打印B.foo(),因为B会覆盖B,动态类型为foo() }是a,因此调用了B

    在您的情况下:由于B.foo()会覆盖String,然后会调用hashCode(),而对于String.hashCode() - 它不会覆盖testClass,因此原始hashCode()被调用。

答案 5 :(得分:0)

方法hashCode() 始终返回一个整数,该整数是对象的hash value。类Object中提供了一个nativ实现。如果要创建自己的类型哈希,则必须覆盖hashCode()

toString()将返回对象的字符串表示形式,并返回hashCode()(如上所述)对象的哈希值。

班级String会覆盖hashCode()。这就是String

的完成方式
public int hashCode() {
    int h = hash;
    int len = count;
    if (h == 0 && len > 0) {
        int off = offset;
        char val[] = value;

        for (int i = 0; i < len; i++) {
            h = 31*h + val[off++];
        }
        hash = h;
    }
    return h;
}

答案 6 :(得分:0)

我认为您因为空字符串的哈希码为 0 而感到困惑。 Hashcode 始终是一个整数,由该类可用的 hashcode 函数计算。 现在,任何自定义类的哈希码由对象类(默认父级)哈希码方法提供,该方法以 int 形式返回该对象的内存地址。(如果没有被自定义类覆盖)

现在您可以将 String 视为一个自定义类,但由其他一些用户创建,这些用户覆盖了 String 类中字符串的哈希码函数,该函数现在计算如下: S[0]*31^(n-1)+S[1]*31^(n-2)+...+s[n] ,0 表示空字符串。 用于评估上述表达式的所有计算都是java的整数计算。你可以参考https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#hashCode()

java 的 String 类重写了 hascode 函数,这样当你在两个不同的 String 对象上调用 hashcode 时,它​​们的字符串相同,会得到相同的 hashcode;在散列数据结构(如散列图)中使用散列技术时,这通常很重要。 所以这个被覆盖的函数为两者提供了相同的哈希码 String s1=new String("你好") 和 String s2=new String("你好") ;而在内存中,它们被存储为不同的字符串。 现在,如果您希望您的自定义类基于该类的某些属性具有相同的哈希码,您可以像 String 一样根据存储在其中的实际字符串覆盖类中的哈希码。

所以在你的情况 1;你得到 0,在 cade 2 中你得到一些 int 形式的内存位置,如上所述。

相关问题