作者:吴小熙1108 | 来源:互联网 | 2023-01-02 13:43
我有一个定义节点的类(一个有三个双坐标的点).
public class Node {
private final double x, y, z;
public Node() {
}
public Node(final double x, final double y, final double z) {
this.x = x;
this.y = y;
this.z = z;
}
public void setCoordinates(final double x, final double y, final double z) {
this.x = x;
this.y = y;
this.z = z;
}
}
我需要创建很多节点并给它们整数ID,但我必须避免重复.
创建节点的方法如下所示:
private Node vertex = new Node(0, 0, 0);
private final AtomicInteger nodeCounter = new AtomicInteger();
private final Map nodeList = new HashMap<>();
public int addNode(final double x, final double y, final double z) {
vertex.setCoordinates(x, y, z);
int nodeId;
if(nodeList.get(vertex) == null) {
nodeId = nodeCounter.incrementAndGet();
nodeList.put(new Node(x, y, z), nodeId);
} else {
nodeId = nodeList.get(vertex);
}
return nodeId;
}
当然,这不起作用,因为总是返回的get
功能.HashMap
null
所以我想我需要覆盖类中的hashCode
方法Node
.
我在这里看到如何为单个double做到这一点,但我不知道如何创建一个考虑节点的三个坐标的哈希函数.
我是否还必须覆盖该equals
功能?或者hashCode函数是否足够?
1> dasblinkenli..:
所以我想我需要覆盖hashCode
Node类中的方法.
这只是交易的一部分.您还需要覆盖equals
以使您的类作为哈希映射的键工作:
@Override
public int hashCode() {
return 31*31*Double.valueOf(x).hashCode()
+ 31*Double.valueOf(y).hashCode()
+ Double.valueOf(z).hashCode();
}
@Override
public boolean equals(Object other) {
if (!(other instanceof Node)) {
return false;
}
Node n = (Node)other;
return x == n.x && y == n.y && z == n.z;
}
在Java 8+中,Double.valueOf(x).hashCode()
应该替换Double.hashCode(x)
为避免不必要的装箱:
@Override
public int hashCode() {
return 31*31*Double.hashCode(x)
+ 31*Double.hashCode(y)
+ Double.hashCode(z);
}
我是否还必须覆盖该equals
功能?或者hashCode
功能足够吗?
是的,你必须始终覆盖equals
沿hashCode
(为什么?)
为什么不只是`return Objects.hash(x,y,z);`?