对在使用容器HashSet存放自定义对象时重写其类的hashcode和equals方法的几点认识
判断是否是相同对象时,hashcode和equals方法的调用顺序
- 先调用
hashcode()方法,再调用equals()方法 - 如果
hashcode()方法得到的哈希值不同,那么两个对象一定不相同,不作后续判断 - 如果
hashcode()方法得到的哈希值相同,那么还得判断equals()方法,根据equals()方法的返回值来具体判断两个对象是否相同 - 为什么哈希值相同,还得再判断equals方法?
可以去看一下我写的一般哈希 思想与模板代码 理解一下哈希的实现思路
可以发现会产生hash冲突的现象,即可能有几个key被存在了相同的hash位置,这时候仅凭借hash值是否相等,不能判断两个对象是否相等,这时候还得根据equals()方法来验证判断下,可以理解为一个双保险。
如果想做一些特殊的去重操作,不同于一般的去重,该怎么有效利用hashcode和equals方法?
这里我给出自己在本科毕业设计中的一个样例。
问题需求
我想在HashSet中存放一个类Comparison,这个类的属性有两个对象se1和se2和他们之间的名称相似度NameSimilarity和类别相似度CategorySimilarity
public class Comparison{private SE se1; //实体1private SE se2; //实体2private double NameSimilarity; //名称相似度private double CategorySimilarity; //类别相似度public Comparison(SE se1, SE se2, double nameSimilarity, double categorySimilarity) {this.se1 = se1;this.se2 = se2;NameSimilarity = nameSimilarity;CategorySimilarity = categorySimilarity;}
}
然后,定义两个Comparison对象怎么才算重复呢?
如果一个Comparison对象拥有实体(se1,se2),另一个Comparison对象拥有(se2,se1)或(se1,se2),则这两个Comparison对象被认为是重复的,即交换对象里的两个SE对象的位置仍然算是一个Comparison对象。
重写hashcode和equals方法
@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Comparison that = (Comparison) o;return Double.compare(that.NameSimilarity, NameSimilarity) == 0 && Double.compare(that.CategorySimilarity, CategorySimilarity) == 0&& ( (se1.equals(that.se1)&&se2.equals(that.se2)) || (se1.equals(that.se2)&&se2.equals(that.se1)) );
}@Overridepublic int hashCode() {return Objects.hash(se1, se2, NameSimilarity, CategorySimilarity);//return Objects.hash(se1) + Objects.hash(se2) + Objects.hash(NameSimilarity, CategorySimilarity);// 让se1和se2的顺序对hash值没有影响就行
}
equals方法中的( (se1.equals(that.se1)&&se2.equals(that.se2)) |(se1.equals(that.se2)&&se2.equals(that.se1)) )描述了上述逻辑。
但是发现这样写,仍然不对,没发发掘交换位置的情况,原来是因为交换位置后,Objects.hash(se1, se2, NameSimilarity, CategorySimilarity);算出来的hashcode完全不一样了,根据前面讲的逻辑,一旦hashcode不一样,就不会再去判断equals方法。
优化
@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Comparison that = (Comparison) o;return Double.compare(that.NameSimilarity, NameSimilarity) == 0 && Double.compare(that.CategorySimilarity, CategorySimilarity) == 0&& ( (se1.equals(that.se1)&&se2.equals(that.se2)) || (se1.equals(that.se2)&&se2.equals(that.se1)) );
}@Overridepublic int hashCode() {//return Objects.hash(se1, se2, NameSimilarity, CategorySimilarity);return Objects.hash(se1) + Objects.hash(se2) + Objects.hash(NameSimilarity, CategorySimilarity);// 让se1和se2的顺序对hash值没有影响就行
}
return Objects.hash(se1) + Objects.hash(se2) + Objects.hash(NameSimilarity, CategorySimilarity);
这样写,可以让se1和se2的顺序对hash值没有影响,但也没有影响性能,也没有丧失hashcode的效果。
相关文章:
对在使用容器HashSet存放自定义对象时重写其类的hashcode和equals方法的几点认识
判断是否是相同对象时,hashcode和equals方法的调用顺序 先调用hashcode()方法,再调用equals()方法如果hashcode()方法得到的哈希值不同,那么两个对象一定不相同,不作后续判断如果hashcode()方法得到的哈希值相同,那么…...
Java集群:单体架构升级到集群架构(二)实现session共享
默认情况下,session是保存在TOMCAT服务器内存中的,如果我们有两个TOMCAT,它们的session是没有共享的。我们这回要做的就是把session保存在redis中,这样两个TOMCAT就可以共享session了。其实这货的详细原理还是很复杂的,…...
MySQL索引及索引失效的分析(MySQL8.0.19)
目录索引数据结构主键索引非主键索引索引在什么时候是有效的?字符串比较大小btween and索引数据结构 主键索引 我们先来看看索引的数据结构,以及我们是如何利用索引来搜索数据的。MySQL的数据存储结构是B树,在叶子节点存储了数据行ÿ…...
第一个 Django 应用
1. 创建项目 1.1 新建项目 首先新建一个项目,名为 mysite,命令如下: django-admin startproject mysite # 或用 django-admin.py运行成功,生成一些目录: mysite/manage.py # 管理 Django 项目的命令行工具mysit…...
001-ksum 求符合条件的 k 个数 1. Two Sum/15. 3Sum/18. 4Sum/
推荐阅读 000-从零开始的数据结构与算法 001-01-ksum 求符合条件的 k 个数 1. Two Sum/15. 3Sum/18. 4Sum/ 002-两数相加 add two numbers 003-无重复字符的最长子串 Longest Substring Without Repeating Characters 004-寻找两个正序数组的中位数 005-最长回文子串 Lon…...
Nginx学习笔记(三)Linux环境下Nginx的安装和部署
目录一、官网下载二、配置基本信息1.上传 Linux2.解压3.安装编译环境4.配置基本信息4.1 配置失败原因(1):没有安装C编译环境4.2 配置失败原因(2):没有安装 PCRE 依赖4.3 配置失败原因(3):没有安装 zlib 依赖5.查看文件列表三、编译安装四、配…...
【十二天学java】day05--数组和循环高级
**# 1.数组 概念: 指的是一种容器,可以同来存储同种数据类型的多个值。 但是数组容器在存储数据的时候,需要结合隐式转换考虑。 比如: 定义了一个int类型的数组。那么boolean。double类型的数据是不能存到这个数组中的&#…...
用队列实现栈和用栈实现队列(C 语言)
目录 一、用队列实现栈 二、 用栈实现队列 一、用队列实现栈 请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。 实现 MyStack 类: void push(int…...
albedo开源框架配置多数据源
前言:公司框架项目一直都没认真阅读过,最近项目需要连接oracle数据,所以尝试使用框架连接多数据库。添加多数据源插件:我们在项目的插件模块内添加多数据源插件:albedo-dynamic-datasource<?xml version"1.0&…...
22张图带你了解IP地址有什么作用
了解IP地址 1、IP地址的格式 在IP协议的报文中,可以得知IP地址是有32个比特,IP地址在计算机中是以二进制的方式处理的,如果全部以二进制的形式来表示,使用跟表达都非常的困难,所以为了人类方便记忆,采用了…...
121.Android 简单的人工智能聊天项目,chatAi,AI聊天项目,GPTAi
//首页xml布局代码: <?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"mat…...
C++ this指针详解
this 是 C 中的一个关键字,也是一个 const 指针,它指向当前对象,通过它可以访问当前对象的所有成员。所谓当前对象,是指正在使用的对象。例如对于stu.show();,stu 就是当前对象,this 就指向 stu。下面是使用…...
CSS 实现六边形柱状图
前言 👏CSS 实现六边形柱状图 速速来Get吧~ 🥇文末分享源代码。记得点赞关注收藏! 1.实现效果 2.实现步骤 定义全局css变量,柱状宽度为–w,最大高度为–h,柱形整体为渐变色,定义上部分颜色为…...
什么是推挽输出,开漏输出?
这篇文章是看B站“工科男孙老师”这个视频的笔记推挽 开漏 高阻 这都是谁想出来的词?? 我觉得讲的很好,做一下笔记 1.什么是IO输出三态 一共有:高电平, 低电平,浮空/高阻态 三种IO态 2.推挽输出 推挽输出能够表示高、…...
【图像分割】Unet系列深度讲解(FCN、UNET、UNET++)
【图像分割】Unet 深度讲解 文章目录【图像分割】Unet 深度讲解1. 介绍1.1 背景介绍:1.2 医学图像特点1.3 图像分割是什么2. Unet发展历程(FCN、Unet、Unet)2.1 全卷积网络-FCN2.1.1 FCN介绍:2.1.2 FCN框架2.1.3 反卷积层2.1.4 输…...
list底层的简单实现(万字长文详解!)
list底层的简单实现 文章目录list底层的简单实现list_node的实现!list_node的构造函数list的迭代器!——重点!list迭代器的成员变量迭代器的构造函数* 重载前置 重载后置 重载前置-- 重载后置-- 重载! 重载 重载-- 重载list的const迭代器——…...
学习Linux只要学会这个命令就够了!
大家好,我是良许。 这段时间又是搬家,又是找新办公室,现在终于安顿下来了,有时间给大家分享干货了。 今天给大家介绍一个 Linux 超级实用命令,有了这个命令,你就可以愉快使用 Linux 上几乎所有常用命令了…...
javascript基础
javascript基础 1概述: JavaScript是目前web开发中不可缺少的脚本语言,js不需要编译即可运行,运行在客户端,需要通过浏览器来解析执行JavaScript代码。 诞生于1995年,当时的主要目的是验证表单的数据是否合法。 JavaS…...
【游戏逆向】某游戏技能库分析
技能库的分析大多是从技能名字入手的,然后再通过传入职业或者ID等信息去到库中去取当前角色的可用技能。下面我们来对《**明月刀》中的技能库进行分析。 首先通过CE对技能名字进行搜索,得到较少的结果,分别对结果进行修改,并再次…...
Pytorch深度学习常用预训练网络模型的下载地址
Resnet:model_urls {‘resnet18’: ‘https://download.pytorch.org/models/resnet18-5c106cde.pth‘,‘resnet34’: ‘https://download.pytorch.org/models/resnet34-333f7ec4.pth‘,‘resnet50’: ‘https://download.pytorch.org/models/resnet50-19c8e357.pth‘,‘resnet…...
eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...
Linux中《基础IO》详细介绍
目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改,实现简单cat命令 输出信息到显示器,你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…...
