首页 > 编程笔记 > Java笔记 阅读:31

Java hashCode()的用法(附带实例)

Java 中的每个类都直接或间接地扩展了类 Object。当类没有显式超类时,它其实隐式扩展了 Object。

Object 类定义了一些适用于任何 Java 对象的方法,如下表所示:

表:java.lang.Object 类的方法
方法 功能描述
String toString() 生成此对象的字符串表示形式,默认情况下为类名和哈希码
boolean equals(Object other) 如果此对象被认为等于 other,则返回 true;如果与 other 不同或 other 为 null,则返回 false。默认情况下,如果两个对象相同,则它们相等。考虑空安全问题建议使用 Objects.equals(obj, other),而不是 obj.equals(other)
int hashCode() 生成此对象的哈希码。相等对象必须具有相同的哈希码。除非被覆盖,否则虚拟机会以某种方式分配哈希码
ClassgetClass() 生成描述该对象所属类的 Class 对象
protected Object clone() 复制此对象。默认情况下,副本是浅拷贝的
protected void finalize() 当垃圾收集器回收此对象时,将会调用此方法。不要覆盖它

哈希码(hash code)是一个从对象派生出的整数值。哈希码应该是乱序的,如果 x 和 y 是两个不相等的对象,那么 x.hashCode() 和 y.hashCode() 有很大概率不同。例如,"Marry".hashCode() 是 2390779,"Myra".hashCode() 是 2413819。

String 类使用以下算法计算哈希码:
int hash = 0;
for (int i = 0; i < length(); i++)
hash = 31 * hash + charAt(i);
hashCode() 和 equals() 方法必须兼容(compatible):如果 x.equals(y) 为真,那么 x.hashCode() == y.hashCode() 也必须为真。正如你所看到的,String 类就是这种情况,因为具有相同字符的字符串产生相同的哈希码。

Object.hashCode() 方法以某种依赖于实现的方式派生哈希码。它可以从对象的内存位置派生,或者从与对象缓存的数字(顺序或伪随机)派生,或者两者的组合。由于 Object.equals() 方法会测试相同的对象,因此唯一重要的是相同对象具有相同的哈希码。

如果重新定义了 equals() 方法,还需要重新定义 hashCode() 方法来保证与 equals() 方法兼容。如果不这样做,那么使用这些类的用户将对象插入到哈希集合或哈希映射中时,他们可能会出错。

在你的 hashCode() 方法中,可以只组合实例变量的哈希码。例如,下面是 Item 类的 hashCode() 方法:
class Item {
   ...
   public int hashCode() {
      return Objects.hash(description, price);
   }
}
Objects.hash 可变参数方法会计算其参数的哈希码并将其组合。该方法是空安全的。

如果你的类有数组类型的实例变量,则应当首先使用静态 Arrays.hashCode() 方法计算其哈希码,该方法计算由数组元素的哈希码组成的一个哈希码。然后将最终结果传递给 Objects.hash。

在接口中,永远不能使用默认方法来重新定义 Object 类中的任何方法。特别是,接口中不能为 toString()、equals() 或 hashCode() 定义默认方法。由于“类优先”的规则,这样的方法永远无法取代 Object.toString()、Object.equals() 或 Object.hashCode()。

相关文章