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

2023-12-12

我有一个类,我重写了 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();

} 

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

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), not equals(Car).

本质上,您已经提供了overload而不是override, so HashMap一直打电话给equals来自基类。

解决这个问题很简单:添加一个执行强制转换的覆盖,并调用equals你写的方法,像这样:

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

注意使用@Override注解。它可以帮助 Java 自动发现此类问题。

注意:解决这个问题后,请考虑实施您的hashCode以更“节俭”的方式。而不是创造一个一次性的(this.getCarName() + this.getCarModel())string 只是为了获取其哈希码,可以考虑重写方法如下:

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);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java 1.7 重写 hashCode() 的行为不符合我的预期 的相关文章

随机推荐

  • Keras减肥

    我的模型有两个输出层 年龄和性别预测层 我想为每个输出层的损失分配不同的权重值 我有以下代码行来执行此操作 model compile loss losses mean squared error losses categorical cr
  • 为什么 FormsAuthentication 的 requireSSL 属性默认为 false!

    注意 这不是与 RequireSSL 属性相关的 ASP NET MVC 问题 那是完全不同的 只是名字相同 ASP NET Forms 身份验证具有需要SSL属性要求 ASP NET 成员资格的身份验证 cookie 只能通过 SSL 发
  • Delegate.Invoke 和 Delegate() 之间的区别

    delegate void DelegateTest DelegateTest delTest 打电话有什么区别delTest Invoke and delTest 两者都会在当前线程上执行委托 对吗 The delTest form 是一
  • 如何使用决策者终止 Spring Batch Split Flow 中的步骤

    我在 Spring Batch 中遇到了以下设计缺陷 步骤必须具有 Next 属性 除非它是最后一个步骤或拆分流的最后一个步骤 Decider 块必须处理 Decider 返回的所有情况 因此 在 Split Flow 中 最后一个 Ste
  • 捆绑了依赖项的 JavaFX jar

    我刚刚提出了一个关于使用javafxpackager制作JavaFX jar的问题 你可以看看here 我的问题是我无法在清单中包含类路径 好吧 当我等待答案时 我尝试了maven antrun plugin反而 它工作得很好 我可以使用依
  • 如何获取struts标签中的JSP scriptlet值

    这是我的代码 如果我执行以下操作 我将不会获得该值
  • 管道“cd”或“popd”输出会阻止更改目录吗?

    我明白 自从 为命令启动一个新进程after管道 任何形式的 shell 命令cmd cd newdir where cmd不更改当前工作目录 将保持原始进程的工作目录不变 更不用说这有点愚蠢了 因为cd不从 stdin 读取输入 但是 在
  • Google Apps 脚本按钮:我可以分配未附加到工作表的“全局”脚本吗?

    我有一个脚本 想将其分配给多个不同电子表格上的按钮 如果我在电子表格上创建一个按钮并引用存储在 Google 驱动器上另一个父文件夹中的脚本 我会收到错误Script function myScript could not be found
  • @autoreleasepool 没有 ARC?

    我是 Xcode 4 2 的新手 还没有完全熟悉 ARC 然而 我确实读到 autoreleasepool 取代了自动释放池的手动使用 并在幕后做了一些特殊的魔法来与 ARC 很好地配合 然而 当我在 Xcode 4 2 中启动一个新项目时
  • 同步动态加载 JavaScript

    我正在使用模块模式 我想做的一件事是动态包含一个外部 JavaScript 文件 执行该文件 然后在return 我的模块 我不知道如何轻松做到这一点 是否有执行伪同步外部脚本加载的标准方法 function myModule var ta
  • 奥利奥:广播接收器不工作

    每当用户拨打新电话时 我试图在我的应用程序上获取通知触发器 我正在我的活动中注册接收器并在 onDestroy 方法中销毁它 以下是注册的代码片段 registerReceiver inComingCall new IncomingCall
  • 在 JavaScript 中序列化/反序列化对象的最佳方法?

    我的应用程序中有许多 JavaScript 对象 例如 function Person age this age age this isOld function return this age gt 60 before serialize
  • 获取 API post XML 请求错误

    我没能做到fetch发布请求 它返回一个400 bad request error fetch http 192 168 1 6 49152 ctl RenderingControl method POST headers SOAPActi
  • 箭头函数比 v8 中的普通独立函数声明更快(性能更高、更轻)吗?

    我问这个问题是因为我和我的同事在编码风格上存在争议 因为他更喜欢箭头函数声明 const sum a b gt a b 我更喜欢旧式的独立函数声明 function sum a b return a b 我的观点是 旧式代码更具可读性 您可
  • 下载进度状态,从 Google 云端硬盘下载文件时?

    我可以从 Google 云端硬盘下载文件 但我想知道下载进度 谁能告诉我该怎么做 我已经尝试过这样下载文件 NSString downloadURL self driveFiles objectAtIndex indexPath row d
  • 源文件与构建模块时不同

    这真让我抓狂 我有一个相当大的项目正在尝试修改 我早些时候注意到当我输入时DbCommand Visual Studio没有对其进行任何语法高亮 我正在使用usingSystem Data Common 尽管没有突出显示任何内容 该项目似乎
  • 如何使用 Inno Setup 创建一个安装程序来提取 .rar 存档的内容?

    我想在 Inno Setup 中创建一个安装程序 它提取预先创建的内容Data rar档案 我的意思是它应该将 rar 存档的内容视为应用程序的文件和文件夹 通过 Inno Setup 使用外部提取实用程序的通用方法 创建档案 将存档嵌入到
  • Material-UI LinearProgress 栏不起作用

    我有一个简单的文件上传实用程序 我正在使用它反应 dropzone 并结合我想使用material ui LinearProgress bar来显示进度 下面显示的是我创建的组件 它呈现文件上传实用程序以及 LinearProgress 栏
  • 在 React 项目上运行 NPM start 后出错

    我已将项目从以前的计算机复制到当前的计算机 跑步后npm install And npm start我的终端给出了这个错误 sh 反应脚本 找不到命令npm 错误 文件shnpm 错误 代码 生命周期npm 错误 错误信息npm 错误 系统
  • Java 1.7 重写 hashCode() 的行为不符合我的预期

    我有一个类 我重写了 hashCode 方法和 equals 方法 equals 方法的行为符合我的预期 但是 hashCode 方法的行为似乎并不符合我的预期 我假设我的期望是不正确的 但不确定为什么 以下是重写的方法 public cl