Java基础--HashCode

如果一个类的对象要用做hashMap的key,那么一定要注意覆盖该类的equals和hashCode方法。

equals()是基类Object的方法,用于判断对象是否有相同地址及是否为同一对象

public boolean equals(Object obj) {
        return (this == obj);
    }

hashCode()是基类Object的native方法,返回int。 

hashCode的通用约定: 

1.在程序运行期间,只要对象不改变,hashCode方法返回的值始终如一。

2.若两个对象equals方法返回相同,hashCode也应该相同。

3.若两个对象equals方法返回不同,hashCode也应该不同。

根据上面的约定,覆盖hashCode方法时注意:

1.需使用对象属性中关键且独立的部分

2.不要使用equals方法中未使用的属性

3.使用equals方法中使用的属性

String类的hashCode方法:

 1 public int hashCode() {
 2         int h = hash;
 3         if (h == 0 && value.length > 0) {
 4             char val[] = value;
 6             for (int i = 0; i < value.length; i++) {
 7                 h = 31 * h + val[i];
 8             }
 9             hash = h;
10         }
11         return h;
12     }

32*d == d<<5   aka   31*d == d<<5-d    

一个例子:

----------------------------

 1 class TestClass {
 2     // 若类较复杂,建议将hashCode缓存,以提高性能
 3     private volatile int hashCode = 0;
 4 
 5     private int i;
 6     private boolean b;
 7     private char c; // 或byte short
 8     private long l;
 9     private float f;
10     private double d;
11     private int[] aa;
12     private String s;
13 
14     @Override
15     public boolean equals(Object o) {
16         if (o == this) {
17             return true;
18         }
19         if (!(o.getClass() == getClass())) {
20             return false;
21         }
22         TestClass ot = (TestClass) o;
23         return i == ot.i && b == ot.b && c == ot.c && l == ot.l && Float.compare(f, ot.f) == 0 && Double.compare(d, ot.d) == 0
24                 && Arrays.equals(aa, ot.aa) && s.equals(ot.s);
25     }
26 
27     @Override
28     public int hashCode() {
29         int result = hashCode;
30         if (result == 0) {
31             result = 31 * result + i;
32             result = 31 * result + Boolean.hashCode(b);
33             result = 31 * result + (int)c;
34             result = 31 * result + Long.hashCode(l);
35             result = 31 * result + Float.hashCode(f);
36             result = 31 * result + Double.hashCode(d);
37             result = 31 * result + Arrays.hashCode(aa);
38             result = 31 * result + s.hashCode();
39             hashCode = result;
40         }
41         return result;
42     }
43     
44     @Override
45     public String toString(){
46         //
47         return s;
48     }
49 
50 }

----------------------------

HashMap

HashMap默认初始容量16,加载因子0.75,容量也就是内部数组table的大小,总是2的n次方,table中的元素为链表,链表的元素为包含key,value,hash和下一元素的Entry。

put方法根据key的hashCode来计算元素在table中的存放位置,不同的key将均匀的散列在table中。

HashMap的扩容将重新计算所有元素在新数组中的位置,所以如果预计存放大量数据,初始容量应该设置更大。

原文地址:https://www.cnblogs.com/luangeng/p/6029482.html