为什么2个对象具有不同的哈希码,但2个String在Java中具有相同的哈希码?

时间:2015-03-25 20:44:05

标签: java dictionary hash hashmap

class A{
    int a;
    A(){
        this.a = 100;
    }
}
//in main, we have:
A a = new A(), b = new A();
//and
String str0 = "123", str1 = "123";

为什么str0和str1的哈希码是相同的,但不是a和b?

3 个答案:

答案 0 :(得分:6)

由于String 会覆盖 Object.hashCode(),而您的课程却没有。

这意味着String类具有hashCode()的特定实现,它将根据String值计算哈希值。因此,对于具有相同值的两个字符串,哈希码将是相同的。

例如,当您创建新类A时,如果您没有为hashCode()提供自己的实现,它将使用类Object中的默认实现。如果哈希码来自完全相同的实例,则默认实现只能保证哈希码相同。

方法Objects.hash()(针对多个值)和Objects.hashCode()(针对单个值)可以更轻松地在您自己的类中实现hashCode()。例如:

class A{
    int a;

    A() {
        this.a = 100;
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(a);
    }
}

请注意,如果用于创建哈希值的属性值在某个时刻发生变化,hashCode()的结果可能也会发生变化。

答案 1 :(得分:2)

因为hashCode()类中java.lang.String的实现被覆盖了。

为了能够在集合中使用String,必须重写实现。

答案 2 :(得分:1)

因为String的hashCode实现已构建为始终为给定顺序中的相同chars集合返回相同的哈希码。而Object.hashCode()将ever对象视为唯一。如果你想知道两个字符串是否是不同的对象那么你可以使用Objects.hashCode(someString)

/**
 * Returns a hash code for this string. The hash code for a
 * {@code String} object is computed as
 * <blockquote><pre>
 * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
 * </pre></blockquote>
 * using {@code int} arithmetic, where {@code s[i]} is the
 * <i>i</i>th character of the string, {@code n} is the length of
 * the string, and {@code ^} indicates exponentiation.
 * (The hash value of the empty string is zero.)
 *
 * @return  a hash code value for this object.
 */
public int hashCode() {
    int h = hash;
    if (h == 0 && value.length > 0) {
        char val[] = value;

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