Java 1.7覆盖hashCode()的行为与我的预期不符 [英] Java 1.7 Override of hashCode() not behaving as I would expect

查看:110
本文介绍了Java 1.7覆盖hashCode()的行为与我的预期不符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a class where I have overridden both the hashCode method as well as the equals method. The equals method behaves as I would expect it to, however the hashCode method does not seem to behave as I would expect. I'm assuming therefor my expectation is incorrect, but not sure why. Below are the overridden methods:

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();

} 

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

Now I have a test class where create two car objects, and call the equals method and then put each instance of car into a HashMap. I set each instance to have the same car Name and Model and calling equals method in fact returns true. However even though each instance returns the same hashCode, when I add them to the HashMap, it keeps two objects int the Map, whereas I would expect the second put to replace the first object in the map ??? Below is the guts of the test class:

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.

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

So this doesn't seem correct to me, I have naturally left some of the code out here, but this is the basic principal. Hoping someone can point out where I have gone wrong here. Note that I did use Eclipse to generate hashCode and equals methods and that worked correctly, however it's bugging me that my implementation of hashCode did not work as I expected, even though both objects seemingly returned the same value for the hashCode. Appreciate anyone's input.

推荐答案

问题是你提供了错误的等于:它应该是等于(对象),而不是等于(汽车)

The problem is that you have provided a wrong equals: it should be equals(Object), not equals(Car).

基本上,你提供了重载而不是覆盖,所以 HashMap 保持不变从基类调用等于

Essentially, you have provided an overload instead of an override, so HashMap keeps calling the equals from the base class.

修复此问题很简单:添加执行转换的覆盖,并调用您编写的等于方法,如下所示:

Fixing this problem is simple: add an override that does the cast, and calls the equals method that you wrote, like this:

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

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

Note the use of @Override annotation. It helps Java help you spot issues like this automatically.

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

Note: with this problem out of the way, consider implementing your hashCode method in a more "frugal" way. Rather than creating a throw-away (this.getCarName() + this.getCarModel()) string simply for the purpose of obtaining its hash code, consider rewriting the method as follows:

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

或在Java 1.7+中你可以写

or in Java 1.7+ you could write

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

这篇关于Java 1.7覆盖hashCode()的行为与我的预期不符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆