Java 1.7重写hashCode()的行为与我预期的不一样

Java 1.7重写hashCode()的行为与我预期的不一样,java,equals,hashcode,Java,Equals,Hashcode,我有一个类,在这个类中我重写了hashCode方法和equals方法。equals方法的行为与我预期的一样,但是hashCode方法的行为似乎与我预期的不同。我假设我的期望是不正确的,但不知道为什么。以下是被覆盖的方法: public class Car extends SomeBaseClass implements Cloneable, Serializable { private static final long serialVersionUID = 1L; private String

我有一个类,在这个类中我重写了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替换Map中的第一个对象???以下是测试课程的核心内容:

HashMap<Car,String> 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.
HashMap-testMap;
汽车测试CAR1=新车();
testCar1.Setcarame(“DaveCar”);
testCar1.setCarModel(“DaveModelTest”);
System.out.println(“carhash1:+testCar1.hashCode());
Car testCar2=新车();
testCar2.Setcarame(“DaveCar”);
testCar2.setCarModel(“DaveModelTest”);
System.out.println(“carhash2:+testCar2.hashCode());
//哈希代码打印相同的数字
System.out.println(“Car 1等于Car 2???”+testCar1.equals(testCar2));
//返回true
testMap.put(testCar1,“3”);
testMap.put(testCar2,“16”);
System.out.println(“映射大小为”+testMap.size());
//我希望这里的尺寸是1,但实际上是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帮助您自动发现这样的问题

注意:在这个问题的解决中,考虑以一种更“节俭”的方式来实现你的<代码> hash码< /代码>方法。而不是创建一个抛出<代码>(this .gCARNAMEL(+)+ .GETCARMMODEL())字符串,只是为了获得哈希代码,考虑重写方法如下:

public int hashCode() {
    return 31*getCarName().hashCode() + getCarModel().hashCode();
}
或者在Java1.7+中,您可以编写

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

问题不在于
.hashCode()
;问题是您没有覆盖
.equals()

看看你的原型:

public boolean equals(Car car)
现在看看

您应该覆盖的是:

public boolean equals(Object obj)

因此出现了错误。您确实正确地实现了hashCode,但是您使用了
对象的
.equals()
实现。

如果您使用
instanceof
null
instanceof
nothing@fge您是对的,实现可以大大缩短。谢谢好的,如果我们要缩短实现,哈希代码实现可以重写为
对象这也会处理空值(好的,只有在1.7版本才可行)@fge你又对了,谢谢!我已经退出Java开发太久了,所以我没有注意到添加了非常受欢迎的
对象
类。谢谢如果
carName
carModel
是最终结果,您可以只计算一次hashCode,并将其存储在局部变量中,以获得最高速度。它们可能是最终的:一般来说,用于生成哈希代码的字段不应该是可变的。