diff --git a/docs/notes/11. 重写equals方法时同时也要重写hashcode方法.md b/docs/notes/11. 重写equals方法时同时也要重写hashcode方法.md index ee2f8a8..cefb5dd 100644 --- a/docs/notes/11. 重写equals方法时同时也要重写hashcode方法.md +++ b/docs/notes/11. 重写equals方法时同时也要重写hashcode方法.md @@ -12,7 +12,6 @@ ```java Map m = new HashMap<>(); - m.put(new PhoneNumber(707, 867, 5309), "Jenny"); ``` @@ -23,7 +22,6 @@ m.put(new PhoneNumber(707, 867, 5309), "Jenny"); ```java // The worst possible legal hashCode implementation - never use! - @Override public int hashCode() { return 42; } ``` @@ -37,7 +35,7 @@ m.put(new PhoneNumber(707, 867, 5309), "Jenny");     -- i. 如果这个属性是基本类型的,使用 `Type.hashCode(f)` 方法计算,其中 `Type` 类是对应属性 `f` 基本类型的包装类。
    -- ii. 如果该属性是一个对象引用,并且该类的 equals 方法通过递归调用 equals 来比较该属性,并递归地调用 hashCode 方法。 如果需要更复杂的比较,则计算此字段的“范式(“canonical representation)”,并在范式上调用 hashCode。 如果该字段的值为空,则使用 0(也可以使用其他常数,但通常来使用 0 表示)。
-      -- iii. 如果属性 `f` 是一个数组,把它看作每个重要的元素都是一个独立的属性。 也就是说,通过递归地应用这些规则计算每个重要元素的哈希码,并且将每个步骤 2.b 的值合并。 如果数组没有重要的元素,则使用一个常量,最好不要为 0。如果所有元素都很重要,则使用 `Arrays.hashCode` 方法。
+      -- iii. 如果属性 `f` 是一个数组,把它看作每个重要的元素都是一个独立的属性。 也就是说,通过递归地应用这些规则计算每个重要元素的哈希码,并且将每个步骤 2.b 的值合并。 如果数组没有重要的元素,则使用一个常量,最好不要为 0。如果所有元素都很重要,则使用 `Arrays.hashCode` 方法。
b. 将步骤 2.a 中属性 c 计算出的哈希码合并为如下结果:`result = 31 * result + c;` @@ -53,18 +51,12 @@ m.put(new PhoneNumber(707, 867, 5309), "Jenny"); ```java // Typical hashCode method - @Override public int hashCode() { - int result = Short.hashCode(areaCode); - result = 31 * result + Short.hashCode(prefix); - result = 31 * result + Short.hashCode(lineNum); - return result; - } ``` @@ -77,12 +69,9 @@ public int hashCode() { ```java // One-line hashCode method - mediocre performance - @Override public int hashCode() { - return Objects.hash(lineNum, prefix, areaCode); - } ``` @@ -90,28 +79,18 @@ public int hashCode() { ```java // hashCode method with lazily initialized cached hash code - private int hashCode; // Automatically initialized to 0 @Override public int hashCode() { - int result = hashCode; - if (result == 0) { - result = Short.hashCode(areaCode); - result = 31 * result + Short.hashCode(prefix); - result = 31 * result + Short.hashCode(lineNum); - hashCode = result; - } - return result; - } ``` @@ -122,7 +101,7 @@ public int hashCode() {   **不要为 hashCode 返回的值提供详细的规范,因此客户端不能合理地依赖它; 你可以改变它的灵活性。** Java 类库中的许多类(例如 String 和 Integer)都将 hashCode 方法返回的确切值指定为实例值的函数。 这不是一个好主意,而是一个我们不得不忍受的错误:它妨碍了在未来版本中改进哈希函数的能力。 如果未指定细节并在散列函数中发现缺陷,或者发现了更好的哈希函数,则可以在后续版本中对其进行更改。   总之,每次重写 equals 方法时都必须重写 hashCode 方法,否则程序将无法正常运行。你的 hashCode 方法必须遵从 Object 类指定的常规约定,并且必须执行合理的工作,将不相等的哈希码分配给不相等的实例。如果使用第 51 页的配方,这很容易实现。如条目 10 所述,AutoValue 框架为手动编写 equals 和 hashCode 方法提供了一个很好的选择,IDE 也提供了一些这样的功能。 - - [1]: http://com.google.common.hash.hashing/ + +[1]: http://com.google.common.hash.hashing/