Java中hashcode的计算方式
Posted 小妖云汐
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中hashcode的计算方式相关的知识,希望对你有一定的参考价值。
Java中hashcode的计算方式
String计算hashCode的方式
/**
* hashcode的计算方式为,以31为权重,举例“java”字符串的计算
* j 的 ASCII码 为 106
* a 的 ASCII码 为 97
* v 的 ASCII码 为 118
* 字符串 va 的 hashcode为 118 * 31 + 97
* 字符串 java 的 hashcode为 106 * 31 * 31 * 31 + 97 * 31 * 31 + 118 * 31 + 97
*/
System.out.println(Integer.valueOf('j')); //ASCII码:106
System.out.println(Integer.valueOf('a')); //ASCII码:97
System.out.println(Integer.valueOf('v')); //ASCII码:118
System.out.println(Integer.valueOf('a')); //ASCII码:97
int hashcode = 106 * 31 * 31 * 31 + 97 * 31 * 31 + 118 * 31 + 97;
System.out.println("hashCode计算的值:" + hashcode); //3254818
System.out.println("Objects hashCode:" + Objects.hashCode("java") ); //3254818
System.out.println("String hashCode:" + "java".hashCode()); //3254818
//Objects.hash在上面的计算方式基础上额外增加了31
System.out.println("Objects hash:" + (3254818 + 31)); //3254849
System.out.println("Objects hash:" + Objects.hash("java") ); //3254849
Objects.hash实际上是由Arrays.hashCode(values)运算得出的,计算过程如下:
hashcode有什么用?
当过多对象进行比较时,需要调用n次equals逐个进行比较,会大大降低效率
但是不同的对象可能会生成相同的hashcode值,所以不能根据hashcode值判断两个对象是否相等,但是可以直接根据hashcode值判断两个对象不等
。
如果两个对象的hashcode值不等,则必定是两个不同的对象。如果要判断两个对象是否真正相等,必须通过equals方法。
Entity重写hashCode方法
- 为什么要重写equals方法?
如果不重写entity的equals方法,默认调用equals,比较的结果并不准确。
public class Users
private int id;
private String name;
public Users(int id,String name)
this.id = id;
this.name = name;
public static void main(String[] args)
Users user1 = new Users(1,"小妖");
Users user2 = new Users(1,"小妖");
System.out.println(user1.equals(user2)); //打印结果:false
在没有重写equals的情况下,默认调用的是Object的equals,和使用“==”比较的结果一样
- 对于值对象,==比较的是两个对象的值
- 对于引用对象,==比较的是两个对象的地址
public boolean equals(Object obj)
return (this == obj);
而重写equals方法之后,可以根据entity本身的属性来判断,该实体类是否相等
public class Users
private int id;
private String name;
public Users(int id,String name)
this.id = id;
this.name = name;
@Override
public boolean equals(Object o)
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Users users = (Users) o;
return id == users.id &&
Objects.equals(name, users.name);
@Override
public int hashCode()
return Objects.hash(id, name);
public static void main(String[] args)
Users user1 = new Users(1,"小妖");
Users user2 = new Users(1,"小妖");
System.out.println(user1.equals(user2)); //打印结果:true
- 为什么要重写hashCode方法?
重写equal方法时,一定要重写hashCode方法!保证相同的对象返回相同的hash值,不同的对象返回不同的hash值。
如果不重写hashCode方法,调用的是Object中的hashCode方法
public native int hashCode();
重写后的hashcode方法会基于entity的属性计算值
@Override
public int hashCode()
return Objects.hash(id, name);
Entity的hashcode方法主要用于将entity放入HashMap、HashSet等集合框架中。
两个对象相等,hashcode一定相等
两个对象不等,hashcode不一定不等
hashcode相等,两个对象不一定相等
hashcode不等,两个对象一定不等
HashMap中计算hashCode的应用
- hashMap中hashCode的计算
- hashMap的大致存取过程
put操作:
当调用put(key,value)方法的时候,会先对键key调用key.hashcode()方法,根据方法返回的hashcode来找到bucket的位置来存Entry对象。
根据hashcode找到对应的bucket之后,通过equals()方法在对应的链表逐一对比,检查这个链表里有没存在相同的key对象。如果有,则用新的value取代旧的value。如果没有,在链表的尾部加上这个新的Entry对象。
get操作:
当调用get(key)的时候,会调用key的hashcode方法获得hashcode。根据hashcode获取相应的bucket。
由于一个bucket对应的链表中可能存有多个Entry,这个时候会调用key的equals方法来找到对应的Entry
以上是关于Java中hashcode的计算方式的主要内容,如果未能解决你的问题,请参考以下文章
Java 中 String 字符串的 hashCode 计算原理