HashCode在散列表中才会使用,equals()方法与hashCode()方法要一起进行修改。
Hash是散列,就是输入任意长度的输入,经过散列函数,计算出固定长度的输出,输出的值就是散列值。
特性:
1、同样输入 --> 同样的输出;
2、不同输入可能会产生相同的Hash值,这时候就产生了“碰撞”
3、Hash值不同,输入必定不同。
HashCode是什么?
1、目的: 为了加快查找的速度。使用HashCode确定散列表中对象的存储地址。
2、规定:如果 o.equals(e),那么默认o.hashCode() == e.hashCode(); (equals() , hashCode() 是Object类中的方法,可以重写。) 因而equals方法的重写要伴随着hashCode()方法的重写。
3、 HashCode相同,不一定对象相同,只能说明存储地址相同。
Object类中的
hashCode
()方法,native方法,是一个本地方法,不是Java语言写的方法。
public
native
int
hashCode
();
HashCode的作用:
相对于使用比较对象的内容,比较HashCode可以更快得判断大量数据的值是否相等。举个例子,比如有100个长度都相当长的字符串,依次比较字符串是否相等,时间会不会很长,每个字符串都很长。而如果算出每个字符串的HashCode(int 类型的),是不是相当于把比较长度较大的String类型,转化成了比较长度较短的int型,所以比较速度就相对快很多。如果两个字符串HashCode相同,这是后再判断字符串本身是不是相等就好了。
为什么说HashCode要在散列中使用:
class
HashCodeTest {
int
i
;
@Override
public
boolean
equals(Object
obj
) {
if
(
this
==
obj
)
return
true
;
if
(
obj
==
null
)
return
false
;
if
(getClass() !=
obj
.getClass())
return
false
;
HashCodeTest
other
= (HashCodeTest)
obj
;
if
(
i
!=
other
.
i
)
return
false
;
return
true
;
}
}
public
class
Test {
public
static
void
main(String[]
args
) {
System.
out
.println(
new
HashCodeTest().hashCode() );
System.
out
.println(
new
HashCodeTest().hashCode() );
System.
out
.println(
new
HashCodeTest().hashCode() );
System.
out
.println(
new
HashCodeTest().hashCode() );
}
}
结果:
31168322
17225372
5433634
2430287
通过
new
HashCodeTest() 创建出的四个对象中, 其i值默认为0, 这四个对象使用equals() 是相等的。 如果将这四个对象置入HashSet时,会发生问题。
HashSet的底层实现是HashMap,会使用到HashCode来确定存放在HashMap中数组的位置。
static
final
int
hash(Object
key
) {
int
h
;
return
(
key
==
null
) ? 0 : (
h
=
key.hashCode()
) ^ (
h
>>> 16);
}
这时就会用到hashCode(),而之前
HashCodeTest四个对象的HashCode不同,很可能会被返回不同的int值。因而就会破坏HashSet的规则————不允许存在相同的(equals()成立)对象,因而有必要重写hashCode()方法。
下面举个例子:
返回此字符串的哈希码。 String 对象的哈希码根据以下公式计算:
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
使用 int 算法,这里 s[i] 是字符串的第 i 个字符, n 是字符串的长度, ^ 表示求幂。(空字符串的哈希值为 0。)
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}