Java 1.7覆盖hashCode()的行为与我的预期不符

我有一个类,我已经覆盖了hashCode方法和equals方法。 equals方法的行为与我期望的一样,但是hashCode方法似乎没有像我期望的那样运行。 我假设因为我的期望不正确,但不确定原因。 以下是重写方法:

public class Car extends SomeBaseClass implements Cloneable, Serializable { private static final long serialVersionUID = 1L; private String id; private String name; private String carName; private String carModel; private String displayTextCar; public boolean equals(Car car) { return (getCarName().equals(car.getCarName()) && getCarModel().equals(car.getCarModel())); } public int hashCode() { return (this.getCarName() + this.getCarModel()).hashCode(); } 

现在我有一个测试类,在其中创建两个car对象,并调用equals方法,然后将每个car实例放入HashMap。 我将每个实例设置为具有相同的汽车名称和模型,并且调用equals方法实际上返回true。 然而,即使每个实例返回相同的hashCode,当我将它们添加到HashMap时,它会将两个对象保留在Map中,而我希望第二个put替换地图中的第一个对象??? 以下是测试类的内容:

 HashMap testMap; Car testCar1 = new Car(); testCar1.setCarName("DaveCar"); testCar1.setCarModel("DaveModelTest"); System.out.println("Car Hash 1: " + testCar1.hashCode()); Car testCar2 = new Car(); testCar2.setCarName("DaveCar"); testCar2.setCarModel("DaveModelTest"); System.out.println("Car Hash 2: " + testCar2.hashCode()); //hashCodes prints identical numbers System.out.println("Car 1 equal Car 2 ?? " + testCar1.equals(testCar2)); //returns true testMap.put(testCar1, "3"); testMap.put(testCar2, "16"); System.out.println("Map size is " + testMap.size()); //I would expect the size to be 1 here, but it's in fact 2. 

所以这对我来说似乎不正确,我自然会在这里留下一些代码,但这是基本原则。 希望有人能指出我在哪里出错了。 请注意,我确实使用Eclipse来生成hashCode和equals方法,并且这些方法正常工作,但是我的错误是我的hashCode实现没有按预期工作,即使两个对象看起来都返回了hashCode的相同值。 感谢任何人的意见。

问题是你提供了一个错误的equals :它应该是equals(Object) ,而不是equals(Car)

本质上,您提供了一个重载而不是重写 ,因此HashMap始终从基类调用equals

修复这个问题很简单:添加一个执行转换的覆盖,并调用你编写的equals方法,如下所示:

 @Override public boolean equals(Object other) { return (other instanceof Car) && equals((Car)other); } 

请注意@Override注释的使用。 它有助于Java帮助您自动发现此类问题。

注意:考虑到这个问题,请考虑以更“节俭”的方式实现hashCode方法。 不是为了获取其哈希码而创建一个抛弃(this.getCarName() + this.getCarModel())字符串,而是考虑重写方法如下:

 public int hashCode() { return 31*getCarName().hashCode() + getCarModel().hashCode(); } 

或者在Java 1.7+中你可以写

 public int hashCode() { // Thanks, fge, for a nice improvement! return Objects.hash(carName, carModel); } 

问题不.hashCode() ; 问题是你没有覆盖.equals()

看看你的原型:

 public boolean equals(Car car) 

现在看看Object的文档 ……

你应该覆盖的是:

 public boolean equals(Object obj) 

因此错误。 您确实正确实现了hashCode,但是您使用了Object.equals()实现。