当前位置: 首页 > 面试题库 >

Java 1.7的hashCode()重写不符合我的预期

李经国
2023-03-14
问题内容

我有一个我重写了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中,而我希望第二个放置项可以替换地图中的第一个对象。以下是测试课程的内容:

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的实现也没有按我的预期工作。感谢任何人的输入。


问题答案:

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

本质上,您提供了一个 重载 而不是 override ,因此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);
}


 类似资料:
  • 在实用服务中,我有两个功能foo和bar。js 在我的测试文件中,我导入了实用ervice.js并窥探了条形图函数。我期望调用间谍计数为1,因为foo被称为,但它是0。如果我错过了什么,请建议。

  • 本文向大家介绍请你解释Object若不重写hashCode()的话,hashCode()如何计算出来的?相关面试题,主要包含被问及请你解释Object若不重写hashCode()的话,hashCode()如何计算出来的?时的应答技巧和注意事项,需要的朋友参考一下 考点:基础 Object 的 hashcode 方法是本地方法,也就是用 c 语言或 c++ 实现的,该方法直接返回对象的 内存地址。

  • 本文向大家介绍hashCode 与 equals ?为什么重写equals时必须重写hashCode方法?相关面试题,主要包含被问及hashCode 与 equals ?为什么重写equals时必须重写hashCode方法?时的应答技巧和注意事项,需要的朋友参考一下 面试官可能会问你:“你重写过 hashcode 和 equals 么,为什么重写equals时必须重写hashCode方法?” ha

  • 在使用CXF3.0.4构建实现的服务器上验证我的请求时,我遇到了一些问题。 但是,当我尝试使用以下wss安全部分运行请求时,我得到了一个错误: 这是一个错误: 但是,当我尝试用另一个实现(它是IBM的一个)对服务器运行相同的请求时,它工作得很好。我从这里读了说明书

  • 我的问题是关于我被重写的hashCode()方法。我知道,如果equals(Object)方法认为两个对象相等,我需要hashCode()为它们返回相同的值。我的直觉告诉我,在某些情况下,这个hashCode()会违反合同。 有没有一种可接受的方法可以在一个重写的equals(Object)方法中使用equalsIgnoreCase(String)方法,并生成一个不违反约定的hashcode?