Java hashCode原理以及与equals()区别联系详解
作者:小虾仁芜湖 发布时间:2023-03-04 15:37:56
1、什么是hashCode
hashCode就是对象的散列码,是根据对象的某些信息推导出的一个整数值,默认情况下表示是对象的存储地址。通过散列码,可以提高检索的效率,主要用于在散列存储结构中快速确定对象的存储地址,如Hashtable、hashMap中。
为什么说hashcode可以提高检索效率呢?我们先看一个例子,如果想判断一个集合是否包含某个对象,最简单的做法是怎样的呢?逐一取出集合中的每个元素与要查找的对象进行比较,当发现该元素与要查找的对象进行equals()比较的结果为true时,则停止继续查找并返回true,否则,返回false。如果一个集合中有很多个元素,比如有一万个元素,并且没有包含要查找的对象时,则意味着你的程序需要从集合中取出一万个元素进行逐一比较才能得到结论,这样做的效率是非常低的。这时,可以采用哈希算法(散列算法)来提高从集合中查找元素的效率,将数据按特定算法直接分配到不同区域上。将集合分成若干个存储区域,每个对象可以计算出一个哈希码,可以将哈希码分组(使用不同的hash函数来计算的),每组分别对应某个存储区域,根据一个对象的哈希码就可以确定该对象应该存储在哪个区域,大大减少查询匹配元素的数量。
比如HashSet就是采用哈希算法存取对象的集合,它内部采用对某个数字n进行取余的方式对哈希码进行分组和划分对象的存储区域,当从HashSet集合中查找某个对象时,Java系统首先调用对象的hashCode()方法获得该对象的哈希码,然后根据哈希吗找到相应的存储区域,最后取得该存储区域内的每个元素与该对象进行equals()比较,这样就不用遍历集合中的所有元素就可以得到结论。
下面通过String类的hashCode()计算一组散列码:
public class HashCodeTest {
public static void main(String[] args) {
int hash= 0;
String s= "ok";
StringBuilder sb = new StringBuilder(s);
System.out.println(s.hashCode() + " " + sb.hashCode());
String t = new String("ok");
StringBuilder tb =new StringBuilder(s);
System.out.println(t.hashCode() + " " + tb.hashCode());
}
}
运行结果:
3548 1829164700
3548 2018699554
我们可以看出,字符串s与t拥有相同的散列码,这是因为字符串的散列码是由内容导出的。而字符串缓冲sb与tb却有着不同的散列码,这是因为StringBuilder没有重写hashCode()方法,它的散列码是由Object类默认的hashCode()计算出来的对象存储地址,所以散列码自然也就不同了。那么该如何重写出一个较好的hashCode方法呢,其实并不难,我们只要合理地组织对象的散列码,就能够让不同的对象产生比较均匀的散列码。例如下面的例子:
public class Model {
private String name;
private double salary;
private int sex;
@Override
public int hashCode() {
return name.hashCode() + new Double(salary).hashCode() + new Integer(sex).hashCode();
}
}
上面的代码我们通过合理的利用各个属性对象的散列码进行组合,最终便能产生一个相对比较好的或者说更加均匀的散列码,当然上面仅仅是个参考例子而已,我们也可以通过其他方式去实现,只要能使散列码更加均匀(所谓的均匀就是每个对象产生的散列码最好都不冲突)就行了。不过这里有点要注意的就是java 7中对hashCode方法做了两个改进,首先java发布者希望我们使用更加安全的调用方式来返回散列码,也就是使用null安全的方法Objects.hashCode(注意不是Object而是java.util.Objects)方法,这个方法的优点是如果参数为null,就只返回0,否则返回对象参数调用的hashCode的结果。Objects.hashCode 源码如下:
public static int hashCode(Object o) {
return o != null ? o.hashCode() : 0;
}
因此我们修改后的代码如下:
import java.util.Objects;
public class Model {
private String name;
private double salary;
private int sex;
@Override
public int hashCode() {
return Objects.hashCode(name) + new Double(salary).hashCode() + new Integer(sex).hashCode();
}
}
java 7还提供了另外一个方法java.util.Objects.hash(Object… objects),当我们需要组合多个散列值时可以调用该方法。进一步简化上述的代码:
import java.util.Objects;
public class Model {
private String name;
private double salary;
private int sex;
@Override
public int hashCode() {
return Objects.hash(name,salary,sex);
}
}
来源:https://blog.csdn.net/qq_43966957/article/details/128093225


猜你喜欢
- 本文实例讲述了WPF设置窗体可以使用鼠标拖动大小的方法。分享给大家供大家参考。具体实现方法如下:private void Window_Lo
- 1.用法介绍方式一:DatatypeConverter说明:使用jdk自带的DatatypeConverter.java类实现,但是jdk版
- 1. 用indexof的方法:public class Test11 {private static int counter = 0;/**
- 前言本文主要给大家介绍的是关于obix协议在java中的配置和使用,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。什么是
- 问题描述需要定时通过websocket接口来推送mysql里面最新的数据,自定义了定时器@Component@Slf4jpublic cla
- 1 synchronized场景回顾目标:synchronized回顾(锁分类–>多线程)概念synchroniz
- 概述:堆排序是利用构建“堆”的方法确定具有最大值的数据元素,并把该元素与最后位置上的元素交换。可将任意一个由n个数据元素构成的序列按照(a1
- 代码从windows下visual studio到andriod平台迁移实现步骤:前言前言也是迁言,从windows的visual stud
- java parseInt()
- 标题index界面加载问题刚开始学习springBoot记录一下遇到的小问题1.index.html加载不出来的问题我习惯性的将index.
- 相信大部分使用Intellij的同学都会遇到这个问题,即使项目使用了spring-boot-devtools,修改了类或者html、js等,
- 人机交互过程中,当我们需要机器给我们反馈不确定的数字结果时,就会需要用到随机数了,那么,在Java中,我们应当如何来生成并使用随机数呢?一、
- 对于某些程序,我们只允许它使用某些特定端口、网络类型或者特定IP类型等信息。这时候,需要使用到防火墙里面的“高级设置”,创建某些特定的入站或
- package com.cq2022.zago.base.util;import java.io.FileReader;import jav
- 之前一段时间,在朋友的推荐下,玩了探探这一款软件,初玩的时候,就发现,这款软件与一般的社交软件如陌陌之类的大相径庭,让我耳目一新,特别是探探
- 定义jdk8发布新特性中,lambda是一大亮点之一。lambda表达式能够简化我们对数据的操作,减少代码量,大大提升我们的开发效率。Lam
- Android 消息机制1.概述Android应用启动时,会默认有一个主线程(UI线程),在这个线程中会关联一个消息队列(MessageQu
- 简介optional类是java8中引入的针对NPE问题的一种优美处理方式,源码作者也希望以此替代null。历史1965年,英国一位名为To
- 协程(Coroutine)这个词其实有很多叫法,比如有的人喜欢称为纤程(Fiber),或者绿色线程(GreenThread)。其实究其本质,
- 初学C++的朋友经常在类中看到public,protected,private以及它们在继承中表示的一些访问范围,很容易搞糊涂。今天本文就来