具有相同的hashCode相等的对象不映射到相同值的HashMap
我使用的是自定义类Vec
在HashMap
的关键。具有相同的hashCode相等的对象不映射到相同值的HashMap
但是两个相等Vec
对象具有相同hashCode()
不会映射到相同的密钥。
我在做什么错?
import java.util.HashMap;
/**
* A 2-element float Vector
*/
class Vec {
public float x;
public float y;
public Vec(float x, float y) {
this.x = x;
this.y = y;
}
public Vec(Vec v) {
this.x = v.x;
this.y = v.y;
}
public boolean equals(Vec v) {
System.out.println("equals called");
return (x == v.x &&
y == v.y);
}
@Override
public int hashCode() {
final int prime = 31;
int result = (Float.floatToIntBits(x)
+ prime * Float.floatToIntBits(y));
System.out.println("hash called: " + result);
return result;
}
}
public class Debug {
public static final void main(String[] args) {
Vec v1 = new Vec(3, 5);
Vec v2 = new Vec(v1);
System.out.println("vecs equal: " + v1.equals(v2));
System.out.println("hashcodes: " + v1.hashCode() + ", " + v2.hashCode());
System.out.println("\nuse map");
HashMap<Vec, Object> map = new HashMap<>();
map.put(v1, new Object());
Object o1 = map.get(v1);
Object o2 = map.get(v2);
System.out.println(o1);
System.out.println(o2);
if (o2 == null) {
throw new RuntimeException("expected o2 not to be null");
}
};
}
输出
equals called
vecs equal: true
hash called: 329252864
hash called: 329252864
hashcodes: 329252864, 329252864
use map
hash called: 329252864
hash called: 329252864
hash called: 329252864
[email protected]
null
Exception in thread "main" java.lang.RuntimeException: expected o2 not to be null
这是你的问题:
public boolean equals(Vec v) {
^^^
我建议您还是使用
@Override
注释
- 在这种情况下,它会给你一个编译错误因为你是不重写Object::equals
。
更改签名:
public boolean equals(Object v) {
^^^^^^
和修改实施,你应该得到你所期望的行为。
阅读从有效的Java http://allenlsy.com/NOTES-of-Effective-Java-5/#36.-consistenly-use-the-override-annotation – rajuGT
你需要注释与@覆盖了equals和使用对象作为参数 级对于这样的实例:
@Override public boolean equals(Object aThat) {
//check for self-comparison
if (this == aThat) return true;
//use instanceof instead of getClass here for two reasons
//1. if need be, it can match any supertype, and not just one class;
//2. it renders an explict check for "that == null" redundant, since
//it does the check for null already - "null instanceof [type]" always
//returns false. (See Effective Java by Joshua Bloch.)
if (!(aThat instanceof Car)) return false;
//Alternative to the above line :
//if (aThat == null || aThat.getClass() != this.getClass()) return false;
//cast to native object is now safe
Car that = (Car)aThat;
//now a proper field-by-field evaluation can be made
return
EqualsUtil.areEqual(this.fName, that.fName) &&
EqualsUtil.areEqual(this.fNumDoors, that.fNumDoors) &&
EqualsUtil.areEqual(this.fOptions, that.fOptions) &&
EqualsUtil.areEqual(this.fGasMileage, that.fGasMileage) &&
EqualsUtil.areEqual(this.fColor, that.fColor) &&
Arrays.equals(this.fMaintenanceChecks, that.fMaintenanceChecks);}
这itemf?此实现不适用于OP的代码,并通过过于复杂,混淆了点。 –
也没有必要标注'@ Override',它只是帮助你找出如果方法实际上覆盖了一个超级的方法,但也没有必要使用它。 – SomeJavaGuy
因为你didn't覆盖'equals'方法,你是用不同的方法签名,因此它只是一种重载方法。签名需要是“boolean equals(Object)”。你介意张贴相关的代码 – SomeJavaGuy