Java hashCode()的用法(附带实例)
Java 中的每个类都直接或间接地扩展了类 Object。当类没有显式超类时,它其实隐式扩展了 Object。
Object 类定义了一些适用于任何 Java 对象的方法,如下表所示:
哈希码(hash code)是一个从对象派生出的整数值。哈希码应该是乱序的,如果 x 和 y 是两个不相等的对象,那么 x.hashCode() 和 y.hashCode() 有很大概率不同。例如,"Marry".hashCode() 是 2390779,"Myra".hashCode() 是 2413819。
String 类使用以下算法计算哈希码:
Object.hashCode() 方法以某种依赖于实现的方式派生哈希码。它可以从对象的内存位置派生,或者从与对象缓存的数字(顺序或伪随机)派生,或者两者的组合。由于 Object.equals() 方法会测试相同的对象,因此唯一重要的是相同对象具有相同的哈希码。
如果重新定义了 equals() 方法,还需要重新定义 hashCode() 方法来保证与 equals() 方法兼容。如果不这样做,那么使用这些类的用户将对象插入到哈希集合或哈希映射中时,他们可能会出错。
在你的 hashCode() 方法中,可以只组合实例变量的哈希码。例如,下面是 Item 类的 hashCode() 方法:
如果你的类有数组类型的实例变量,则应当首先使用静态 Arrays.hashCode() 方法计算其哈希码,该方法计算由数组元素的哈希码组成的一个哈希码。然后将最终结果传递给 Objects.hash。
在接口中,永远不能使用默认方法来重新定义 Object 类中的任何方法。特别是,接口中不能为 toString()、equals() 或 hashCode() 定义默认方法。由于“类优先”的规则,这样的方法永远无法取代 Object.toString()、Object.equals() 或 Object.hashCode()。
Object 类定义了一些适用于任何 Java 对象的方法,如下表所示:
方法 | 功能描述 |
---|---|
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()。