创建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); }
说完这一切后,我有几个问题:
- 由于我实现了一个新的
equals()
方法,我应该实现一个新的hashCode()
方法吗? - 如何使用这些变量实现新的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就像保存元素的盒子一样。 规则是:
- 等元素必须在同一个框中(具有相同的hashCode) – 当然;
- 不相等的元素可以在相同或不同的框中。
然后你返回常量,你遵守这两条规则,但它可以显着降低不小列表上的性能(因为JVM将在所有元素中查找,而不是仅在同一个框中的元素中查找)。 但是返回常数是不好的方法。
PS:对不起我的写作。 英语不是我的母语。
PPS:通常你必须以与equals相同的方式实现hashCode方法(使用相同的元素)