一、hashcode简介
注意:
public int hashCode()方法返回对象的哈希码值。 这种方法是为了散列表,如HashMap。
第一条: 只要在执行Java应用程序时多次在同一个对象上调用该方法, hashCode方法必须始终返回相同的整数。
第二条: 如果根据equals(Object)方法两个对象相等,则在两个对象中的每个对象上调用hashCode方法必须产生相同的整数结果。
第三条: 不要求如果两个对象根据equals(java.lang.Object)方法不相等,那么在两个对象中的每个对象上调用hashCode方法必须产生不同的整数结果。 但是,程序员应该意识到,为不等对象生成不同的整数结果可能会提高哈希表的性能,减少哈希碰撞。
由类别Object定义的hashCode方法确实为不同对象返回不同的整数,未重写方法时一般通过将对象的内部地址转换为整数来实现,重写后一般通过将对象的内容转换为整数来实现。
哈希表: 哈希表是结合了直接寻址和链式寻址两种方式,所需要的就是将需要加入哈希表的数据首先计算哈希值,其实就是预先分个组,然后再将数据挂到分组后的链表后面,随着添加的数据越来越多,分组链上会挂接更多的数据,同一个分组链上的数据必定具有相同的哈希值,java中的hash函数返回的是int类型的,也就是说,最多允许存在2^32个分组,也是有限的,所以出现相同的哈希码就不稀奇了
总结:
1、hashcode相等,equals不一定相等,这也是哈希碰撞产生的原因。
2、equals相等,若没有重写equals方法,则为同一个对象,其对应的hashcode相等,若重写了equals方法,但是没有重写hashcode方法,则不一定相等,要是重写了hashcode方法则相等。
二、包装类型
包装类型全都重写了hashcode方法
1)、Byte、Short、Integer、Long对应的hashcode方法,均是返回原值
Integer a = 1;
System.out.println(a.hashCode());//1
Byte b = 2;
System.out.println(b.hashCode());//2
Short d = 3;
System.out.println(d.hashCode());//3
Long e = 4L;
System.out.println(e.hashCode());//4
重写后的方法:Byte、Short、Integer、Long方法类似
@Override
public int hashCode() {
return Short.hashCode(value);
}
public static int hashCode(short value) {
return (int)value;
}
2)、Character对应的hashcode方法,返回的是字符对应的ASCII码值(包含0-9、a-z、A-Z以及一些字符)
Character f = '!';
System.out.println(f.hashCode());//33
重写后的方法
@Override
public int hashCode() {
return Character.hashCode(value);
}
public static int hashCode(char value) {
return (int)value;
}
3)、Double、Float对应的hashcode方法,返回的是经过计算的值,与地址无关,也和数据类型无关
Double g = 2.0;
System.out.println(g.hashCode());//1073741824
Double g1 = 2.0;
System.out.println(g.hashCode() == g1.hashCode());//true
Float h = 2.0F;
System.out.println(h.hashCode());//1073741824
重写后的方法
@Override
public int hashCode() {
return Double.hashCode(value);
}
public static int hashCode(double value) {
long bits = doubleToLongBits(value);
return (int)(bits ^ (bits >>> 32));
}
public static long doubleToLongBits(double value) {
long result = doubleToRawLongBits(value);
// Check for NaN based on values of bit fields, maximum
// exponent and nonzero significand.
if ( ((result & DoubleConsts.EXP_BIT_MASK) ==
DoubleConsts.EXP_BIT_MASK) &&
(result & DoubleConsts.SIGNIF_BIT_MASK) != 0L)
result = 0x7ff8000000000000L;
return result;
}
4)、Boolean对应的hashcode方法,返回的是固定的两个值,true返回1231,false返回1237
Boolean i = true;
System.out.println(i.hashCode());//1231
重写后的方法
@Override
public int hashCode() {
return Boolean.hashCode(value);
}
public static int hashCode(boolean value) {
return value ? 1231 : 1237;
}
二、引用数据类型
分析实例解释
public class People {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public People() {
}
public People(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
People people = (People) o;
return age == people.age &&
Objects.equals(name, people.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
Set<People> set = new HashSet<>();
set.add(xiaoer);
set.add(xiaomi);
如果想完整的使用HashSet类那么最少要重写equals()和hashCode()方法。重写hashCode() 用于获得元素的存储位置,重写equals() 用于在两个元素的位置相同的时候比较两个元素是否相等。
重写后的方法。
@Override
public int hashCode() {
return Objects.hash(name, age);
}
public static int hash(Object... values) {
return Arrays.hashCode(values);
}
public static int hashCode(Object a[]) {
if (a == null)
return 0;
int result = 1;
for (Object element : a)
result = 31 * result + (element == null ? 0 : element.hashCode());
return result;
}
People xiaomi = new People("小米",4);
People xiaoer = new People("小米",4);
System.out.println(xiaoer.hashCode() == xiaomi.hashCode());//重写后,ture
System.out.println(xiaoer.hashCode() == xiaomi.hashCode());//重写前,false
本文详细介绍了Java中hashCode方法的基本概念,包括其在哈希表中的作用、重写规则及注意事项。同时,文章对比分析了基本类型与引用类型在hashCode计算上的差异,并提供了实例代码说明equals与hashCode的关系。
1337

被折叠的 条评论
为什么被折叠?



