API文档中HashCode和equals方法定义java
public int hashCode()程序员 |
返回该对象的哈希码值。支持此方法是为了提升哈希表性能。hashCode的常规协定是编程
|
public boolean equals()数组 |
指示其余某个对象是否与此对象“相等”。equals 方法在非空对象引用上实现相等关系:编程语言
|
当一个类有本身特有的“逻辑相等”概念(不一样于对象身份的概念)时,须要重写equals方法性能
【1】.使用instanceof操做符检查“实参是否为正确的类型”。优化
【2】.对于类中的每个“关键域”,检查实参中的域与当前对象中对应的阈值。this
【2.1】对于非float和double类型的原语类型域,使用==比较spa
【2.2】对于对象引用域,递归调用equals方法设计
【2.3】对于float域,使用Float.floatToIntBits(afloat)转化为int,再使用==比较。
【2.4】对于数组域,调用Arrays.equals方法.
【1】.把某个非零常数值,保存在int变量result中
【2】.对于对象中每个关键域f(指equals方法中考虑的每个域):
【2.1】boolean型,计算(f?0:1)
【2.2】byte,char,short型,计算(int)
【2.3】long型,计算(int)(f ^(f >>>32))
【2.4】float型,计算Float.floatToIntBits(afloat)
【2.5】double型,计算Double.doubleToLongBits(abouble)获得一个long,再执行[2.3]
【2.6】对象引用,递归调用它的hashCode方法
【2.7】数组域,对其中每一个元素调用它的hashCode方法
【3】.将上面计算获得的散列码保存到int变量c中,而后执行result=37*result +c;
【4】.返回result
在Object类中定义的hashCode方法代码以下:
public native int hashCode();
这说明hashCode()本地机器相关的方法。jre6中String实现hashCode()的代码以下:
/** * Returns a hash code for this string. The hash code for a * {@code String} object is computed as * <blockquote><pre> * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] * </pre></blockquote> * using {@code int} arithmetic, where {@code s[i]} is the * <i>i</i>th 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; }
String实现hashCode()方法中利用了公式s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]。对这公式的解读:
s[i]是string的第i个字符,n是String的长度。31为啥呢?之因此选择31,是由于它是个奇素数,若是乘数是偶数,而且乘法溢出的话,信息就会丢失,由于与2相乘等价于移位运算。使用素数的好处并非很明显,可是习惯上都使用素数来计算散列结果。31有个很好的特性,就是用移位和减法来代替乘法,能够获得更好的性能:31*i==(i<<5)-i。如今的VM能够自动完成这种优化。