在java中哈希表实现的等于方法有利吗?

时间:2011-08-05 17:59:32

标签: java

为了哈希表的好处,我们有两个方法hashcode和equals.Internally当我们在hastable中添加一个键值对时,它首先进入key的哈希码方法并检查它是否等于任何先前键的哈希码值。如果不是那么它只是在哈希表中添加键值对,但如果它是相等的,那么它进入equals方法,我们再次提供一些逻辑来检查对象是否相等。所以我的问题是我们正在做的工作在equals方法中,我们可以消除它并在hashcode方法中放入相同类型的逻辑,我们提供不同的hashcode(取决于我们在equals方法中放置的逻辑)。通过这种方式,我们可以仅使用哈希码mthod来管理哈希表,并且无需使用equals方法。

以Employee类为例,我们将id,salary和name作为其状态。我们使用Employee作为哈希表中的键。所以我们以满足hashcode和equals方法两种方式的方式覆盖哈希码。所以需要相同的方法。

我知道我在这里遗漏了一些东西。寻找它。

5 个答案:

答案 0 :(得分:3)

问题在于,您无法保证(作为一般条件)哈希码始终是唯一的。

您可以创建一个单独的类,例如Employee应该由employeeId唯一标识。没有理由你的哈希码不能简单地return employeeId; - 你会保证这种方式的唯一性。

但是,一般的对象会有更多。考虑一个坐标类

class Coordinate {
    int x;
    int y;
    int z;

    public boolean equals(Object o) {
        if(o instanceof Coordinate) {
            Coordinate c = (Coordinate)o;
            return x == c.x && y == c.y && z == c.z;
        }
        return false;
    }

    public int hashCode() {
        return x ^ y ^ z;
    }
}

你的x y和z会产生2 ^ 96种不同的唯一性组合,但只有2 ^ 32种可能的哈希码。例如,1,2,3对3,2,1都是相同的。现在你可以改进这个以使哈希码像

public int hashCode(){          int c = x;          c * = 31 + y;          c * = 31 + z;          返回c;     }

但这不会解决问题 - 您仍然可以提出数千种会导致哈希码冲突的组合。

但不要害怕 - 有你所描述的东西:它们被称为Perfect Hashes

答案 1 :(得分:3)

是的,你错过了什么。

首先:hashCode返回一个int,因此只能返回2 ^ 32个不同的值。因此,需要等于能够区分具有相同哈希码的值。

第二:哈希表使用hashCode模数它维护的桶数。因此,即使两个键具有不同的hashCodes,它们也可能属于同一个桶,并且必须使用equals来区分它们。

答案 2 :(得分:2)

您缺少的是某些数据无法用有限整数唯一表示。 String就是一个例子。

此外,当hashCodes相同时,equals仅使用 。元素被放入“桶”中,通常覆盖数百万个可能的hashCode值(使用模运算符)。因此,即使每个可能的对象都有一个唯一的hashCode,你仍然需要仔细检查所有内容。

答案 3 :(得分:2)

问题是hashCode()返回int,并且只有2 ^ 32个不同的哈希码。因此,对于具有超过2 ^ 32个不同状态的类(即几乎所有内容),无法避免为某些对象返回相同的哈希码,即使它们不相等。

答案 4 :(得分:0)

  

所以我的问题是我们在equals方法中所做的工作,我们可以消除它并在hashcode方法中放入相同类型的逻辑,我们提供不同的hashcode(取决于我们在equals方法中放置的逻辑)。

equals方法用于防止将重复键插入Map(如果您使用API​​文档);这包括HashMaps和HashTables。另一方面,hashcode方法用于优化查找,但不能依赖于比较两个键的相等性,因为存在哈希冲突的可能性。 Map文档明确指出:

  

实现可以自由地实现优化,从而避免使用equals调用,例如,首先比较两个键的哈希码。

如果密钥之间发生哈希冲突,则单个存储桶将为两个不同的密钥存储两个或多个值,并且必须顺序遍历存储桶以查找与密钥匹配的值,这是最坏的情况。这就是使用hashcode进行比较的优化原因,因为匹配键的实际值只能通过equals方法获得。请注意,这假设用于计算哈希码的相同字段也用于比较相等。

相关问题