Object类的一个重要方法之一:hashCode();首先看一下Object中对此方法的定义:
/**
* Returns a hash code value for the object. This method is
* supported for the benefit of hash tables such as those provided by
* {@link java.util.HashMap}.
*
* The general contract of {@code hashCode} is:
*
* - Whenever it is invoked on the same object more than once during
* an execution of a Java application, the {@code hashCode} method
* must consistently return the same integer, provided no information
* used in {@code equals} comparisons on the object is modified.
* This integer need not remain consistent from one execution of an
* application to another execution of the same application.
*
- If two objects are equal according to the {@code equals(Object)}
* method, then calling the {@code hashCode} method on each of
* the two objects must produce the same integer result.
*
- It is not required that if two objects are unequal
* according to the {@link java.lang.Object#equals(java.lang.Object)}
* method, then calling the {@code hashCode} method on each of the
* two objects must produce distinct integer results. However, the
* programmer should be aware that producing distinct integer results
* for unequal objects may improve the performance of hash tables.
*
*
* As much as is reasonably practical, the hashCode method defined by
* class {@code Object} does return distinct integers for distinct
* objects. (This is typically implemented by converting the internal
* address of the object into an integer, but this implementation
* technique is not required by the
* Java™ programming language.)
*
* @return a hash code value for this object.
* @see java.lang.Object#equals(java.lang.Object)
* @see java.lang.System#identityHashCode
*/
public native int hashCode();
1.在运行的同一个Java应用程序中,如果一个对象多次执行hashCode()方法,必须都返回同一个hash值。
2.如果通过equals()方法判断的两个相等的对象,则调用hashCode()时也会返回同一个hash值。
3.对于equals()方法判断不等的两个对象却没有必要返回不同的hash值,也就是说,如果两个对象不等,却返回同一个hash值,这个是正常的现象。所以说如果hashCode()的值相等,则两个对象equals()不一定相等;但是当两个对象equals()相等,则hashCode()一定相等。但是,程序员应该要注意一个问题,那就是对不相等的对象返回不同的hash值能有效提升hash表的性能。
因为Java中所有的类都是Object类的子类,所以所有类都有hashCode()方法,比如Integer的hashCode()方法就返回Integer值本身,这里以String的实现为例,看一下hashCode()方法是如何实现的,首先看下代码:
/**
* Returns a hash code for this string. The hash code for a
* {@code String} object is computed as
*
* s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
*
* using {@code int} arithmetic, where {@code s[i]} is the
* ith character of the string, {@code n} is the length of
* the string, and {@code ^} indicates exponentiation.
* (The hash value of the empty string is zero.)
*
* @return a hash code value for this object.
*/
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;
}
/** The value is used for character storage. */
private final char value[];
定义一个String str = "aaa";
在进入hashCode()方法中时,value的值为['a','a','a'],这里hash的值默认初始为0,根据hashCode()实现算法:s[0]31^(n-1) + s[1]31^(n-2) + ... + s[n-1],进入for循环后,
(1). 第一次循环, h = 31 * 0 + a,这里由于a是char类型,而h是int类型,那这里就涉及到了char类型转为int类型,也就是字符对应的ASCII码值,'a'字符转换为ASCII码为97,所以这里的h值为97;
(2). 第二次循环,h = 31 * 97 + 97,为3104;
(3). 第三次循环,h = 3104 * 97 + 97,为96321。
所以字符串"aaa"对应的hash值为96321,这是String类对hashCode()方法的实现。
hashCode()方法经常用在一些数据的存储、比较、分类等场景中用到,比如之前我看到的一个java的面试题目:给定a、b两个文件,各存放50亿个url,每个url各占64字节,内存限制是4G,让你找出a、b文件共同的url?这种问题的解决办法用分而治之就可以实现,获取每个url的hash值,如果两个url相等,那么其hash值一定相等。所以这种思想是可以很好的去解决一些实际的问题的。