创建hashCode()方法 – Java

我在为我创建的类编写hashCode()方法时遇到了一些麻烦。 此类旨在在TreeSet中使用,因此,它实现了Comparable。 该类具有以下变量:

 public class Node implements Comparable { Matrix matrix; int[] coordinates= new int[2]; Node father; int depth; int cost; 

这是compareTo()方法的实现。 我希望TreeSet按其成本组织这些Node结构,因此, compareTo()返回简单减法的结果。

 public int compareTo(Node nodeToCompare) { return this.cost - nodeToCompare.cost; } 

我还实现了equals()方法。

 public boolean equals(Object objectToCompare) { if(objectToCompare== this) {return true;} if(objectToCompare== null || objectToCompare.getClass()!= this.getClass()) {return false;} Node objectNode= (Node) objectToCompare; return this.father.equals(objectNode.father) && this.depth== objectNode.depth && this.cost== objectNode.cost && this.matrix.equals(objectNode.matrix) && Arrays.equals(this.coordinates, objectNode.coordinates); } 

说完这一切后,我有几个问题:

  1. 由于我实现了一个新的equals()方法,我应该实现一个新的hashCode()方法吗?
  2. 如何使用这些变量实现新的hashCode method() ? (注意,Matrix类型的变量矩阵已经实现了hashCode()方法)

就这样!

您的compareTo方法与您的equals方法不一致:您的compareTo方法表示如果两个实例具有相同的cost则它们是等效的 – 这样TreeSet最多只能包含一个具有给定cost实例 – 但是您的equals方法说如果它们具有相同的cost 并且在各种其他方面是相同的,它们只是等价的。

所以,假设你的equals方法是正确的:

  • 您需要修复compareTo方法以使其与之保持一致。
  • 你需要创建一个与之一致的hashCode方法。 我建议使用java.util.List.hashCode()使用的相同逻辑,这是一种直接有效的方法来按特定顺序组装组件对象的哈希码; 基本上你会写一些像:
      int hashCode = 1;
     hashCode = 31 * hashCode +(father == null?0:father.hashCode());
     hashCode = 31 * hashCode + depth;
     hashCode = 31 * hashCode + cost;
     hashCode = 31 * hashCode + matrix.hashCode();
     hashCode = 31 * hashCode + java.util.Arrays.hashCode(coordinates);
     return hashCode; 

Intellij IDEA可以将此作为“右键单击”function。 只要看到它正确完成就会教你很多。

你应该在任何情况下都覆盖它们。

hashCode方法的契约声明如果两个对象相等,那么调用hashCode()应该给你相同的整数结果。 相反的情况不一定是真的,即如果两个hashCode相同,则对象不必彼此相等。

查看你的equals方法(需要变量转换btw),你可以添加所有需要等于equals方法的内部成员变量的hashCodes来给出true。 例如

 public int hashCode() { return this.matrix.hashCode() + this.coordinates[0] + this.coordinates[1] + this.father.hashCode() + this.depth + this.cost; } 

上面假设矩阵和父亲永远不会为空,你需要确保检查空值,如果不是这样的话。

如果你觉得更冒险,你可以将上面的几个与素数相乘,以确保你不会得到不同数据的hashCode冲突(如果你在hashTables和hashMaps中使用你的类,这将有助于提高性能)。 如果你需要满足空值,上面的方法可以写得更好一点:

 public int hashCode() { return ((this.matrix == null) ? 0 : this.matrix.hashCode()) + 17 * this.coordinates[0] + this.coordinates[1] + ((this.father == null) ? 0 : this.father.hashCode()) + 31 * this.depth + 19 * this.cost; } 

如果你的集合很小,你可以从hashCode方法返回常量。 它用于快速查找。 hashCodes就像保存元素的盒子一样。 规则是:

  1. 等元素必须在同一个框中(具有相同的hashCode) – 当然;
  2. 不相等的元素可以在相同或不同的框中。

然后你返回常量,你遵守这两条规则,但它可以显着降低不小列表上的性能(因为JVM将在所有元素中查找,而不是仅在同一个框中的元素中查找)。 但是返回常数是不好的方法。

PS:对不起我的写作。 英语不是我的母语。

PPS:通常你必须以与equals相同的方式实现hashCode方法(使用相同的元素)