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
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
Android实现关机后数据不会丢失问题
![](https://img.aspxhome.com/file/2023/1/104661_0s.jpg)
Spring Boot Maven Plugin打包异常解决方案
![](https://img.aspxhome.com/file/2023/6/101796_0s.png)
Java多线程读写锁ReentrantReadWriteLock类详解
![](https://img.aspxhome.com/file/2023/3/132203_0s.jpg)
java对象拷贝常见面试题及应答汇总
解决java 分割字符串成数组时,小圆点不能直接进行分割的问题
Java线程的生命周期的详解
java实现单词小游戏
![](https://img.aspxhome.com/file/2023/2/59522_0s.png)
mybatis 实现多层级collection嵌套
![](https://img.aspxhome.com/file/2023/1/122201_0s.png)
Java方法的参数传递机制实例详解
![](https://img.aspxhome.com/file/2023/9/63419_0s.png)
Java 实战项目锤炼之网上图书馆管理系统的实现流程
![](https://img.aspxhome.com/file/2023/7/121957_0s.png)
Android中自定义ImageView添加文字说明详解
![](https://img.aspxhome.com/file/2023/4/126664_0s.png)
C#中ExecuteNonQuery()返回值注意点分析
c#中虚函数的相关使用方法
Android实现购物车添加商品特效
![](https://img.aspxhome.com/file/2023/3/101823_0s.gif)
Unity实现旋转扭曲图像特效
![](https://img.aspxhome.com/file/2023/2/111272_0s.png)
Android开发应用第一步 安装及配置模拟器Genymotion
![](https://img.aspxhome.com/file/2023/4/91004_0s.png)
Java异常ClassCastException的解决
Jenkins自动化打包为war包
![](https://img.aspxhome.com/file/2023/2/103992_0s.jpg)
Java JVM中线程状态详解
![](https://img.aspxhome.com/file/2023/9/75759_0s.jpg)