2016-01-20 127 views
0

我使用的是自定义类VecHashMap的关键。具有相同的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 
+1

因为你didn't覆盖'equals'方法,你是用不同的方法签名,因此它只是一种重载方法。签名需要是“boolean equals(Object)”。你介意张贴相关的代码 – SomeJavaGuy

回答

9

这是你的问题:

public boolean equals(Vec v) { 
         ^^^ 
我建议您还是使用 @Override注释

- 在这种情况下,它会给你一个编译错误因为你是不重写Object::equals

更改签名:

public boolean equals(Object v) { 
         ^^^^^^ 

和修改实施,你应该得到你所期望的行为。

+0

阅读从有效的Java http://allenlsy.com/NOTES-of-Effective-Java-5/#36.-consistenly-use-the-override-annotation – rajuGT

-2

你需要注释与@覆盖了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);} 
+1

这itemf?此实现不适用于OP的代码,并通过过于复杂,混淆了点。 –

+0

也没有必要标注'@ Override',它只是帮助你找出如果方法实际上覆盖了一个超级的方法,但也没有必要使用它。 – SomeJavaGuy

相关问题