Dictionary 为什么如果实现了hashCode方法,那么对于数据类型中的键,还必须实现equals方法?

Dictionary 为什么如果实现了hashCode方法,那么对于数据类型中的键,还必须实现equals方法?,dictionary,Dictionary,数据类型:字典键 有人能告诉我同时实现两者(hashCode/equals)的重要性吗。因为我认为如果我们实现hashCode方法equals,我们将比较hashCodes并给出等式 仅仅因为散列码相等并不意味着底层对象相等。可能的哈希代码数量有限,因此必然会发生冲突。您应该实现一个健壮的.Equals(),以便您可以实际测试相等性。哈希代码不能保证唯一性。例如,在大多数语言中,哈希代码采用2^32个值。如果您有一个4整数的类,那么该类可能有多少唯一的状态/实例?(2^32)^4. 这意味着即使

数据类型:字典键


有人能告诉我同时实现两者(hashCode/equals)的重要性吗。因为我认为如果我们实现hashCode方法equals,我们将比较hashCodes并给出等式

仅仅因为散列码相等并不意味着底层对象相等。可能的哈希代码数量有限,因此必然会发生冲突。您应该实现一个健壮的
.Equals()
,以便您可以实际测试相等性。

哈希代码不能保证唯一性。例如,在大多数语言中,哈希代码采用2^32个值。如果您有一个4整数的类,那么该类可能有多少唯一的状态/实例?(2^32)^4. 这意味着即使实现了一个完美的哈希代码,仍然会有2^(32*3)个冲突,其中一对不同的对象具有相同的哈希代码


因此,HashCode被用作第一个“快速”比较,以查找与您正在查找的对象相似的对象。一旦你进入一组对象,就会检查每个对象是否相等,看看是否有一个对象正是你想要的。

问题是,仅仅因为两个对象具有相同的哈希代码并不意味着它们相等

只有2^32个可能的哈希代码(32位整数)。仔细想想,你会发现可能的字符串数量要大得多。因此,并非每个字符串都有唯一的哈希代码

而且,许多类的
GetHashCode
方法实现得很差

例如,下面是.Net源代码中的
Point.GetHashCode

public override int GetHashCode() { 
    return x ^ y; 
}

请注意,
(2,3)
将具有与
(3,2)
相同的hashcode,即使它们不相等。尽管有一些没有表现出这种行为,但根据定义,它们仍然不是唯一的。

IMHO,实现hashcode和equals的原因如下:

哈希表允许基于键快速访问元素。这是可能的,因为它的实施

哈希表内部使用bucket存储其值。将每个桶看作一个数组。 还有一系列这样的桶。因此它变成了一个二维数组。键的hashcode是一种机制,通过该机制,哈希表可以直接跳转到存储值的bucket的索引

例如:

下面我为一个类编写了代码,我将使用该类作为HashMap实例的键

package com.aneesh.hashtable;  
import java.util.HashMap;  
public class Key {

private String key;

public Key(String key){
    this.key = key;
}


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


@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Key other = (Key) obj;
    if (key == null) {
        if (other.key != null)
            return false;
    } else if (!key.equals(other.key))
        return false;
    return true;
}


public static void main(String[] args) {

    HashMap<Key, String> hashMap = new HashMap<Key, String>();
    hashMap.put(new Key("a"), "java");
    hashMap.put(new Key("k"), "Python");

    System.out.println(hashMap.get(new Key("a")));
    System.out.println(hashMap.get(new Key("k")));

}
}
因此(“a,“java”)的键、值对将存储为第7个bucket中的第一个元素

当您执行hashMap.put(newkey(“k”),“python”); 桶索引再次计算为 indexofBucket=key.hashCode()%numberofbucket//7,其中key=“k”

这是同一个桶,第七个指数的桶

现在,当您通过键检索值时

hashMap.get(new Key("a"));
哈希表将计算出索引,因此:

indexOfBucket = key.hashCode() % numberOfBuckets //7
此时,哈希表将在bucket中找到两个元素。现在,它必须返回的元素将由(在一个简单的实现中,我猜)迭代每个元素并比较键的相等值来决定。如果没有相等值,哈希表甚至可能无法找到您添加到其中的元素

要查看此操作,请注释掉Key类的equals实现并运行代码

null  
null 
打印为输出,而使用equals实现后,您将看到

"java",  
"python"

长期受伤的解释,但希望有帮助

,但我们根据数据类型中的值生成hashCode,因此我们为不同的成员值生成不同的hashCode,为相同的成员值生成相同的hashCode(?)具有相同成员值的两个对象将生成相同的哈希代码,但这并不意味着它们是相同的对象。实现Equals是为了确保两个对象引用指向相同的对象,而不仅仅是具有相同属性值的对象。
"java",  
"python"