Java集合(7):散列与散列码
? ? ? ?散列的價(jià)值在于速度。我們使用數(shù)組來(lái)保存鍵的信息,這個(gè)信息并不是鍵本身,而是通過(guò)鍵對(duì)象生成一個(gè)數(shù)字(散列碼),作為數(shù)組下標(biāo)。由于數(shù)組的容量是固定的,而散列容器的大小是可變的,所以不同的鍵可以產(chǎn)生相同的數(shù)組下標(biāo)(散列碼)。也就是說(shuō),可能會(huì)有沖突(當(dāng)然也有特例,比如EnumMap和EnumSet)。所以,數(shù)組的值存放著一個(gè)保存所有相同散列碼的值的list(引用)。然后對(duì)list中的值使用equals進(jìn)行線(xiàn)性查詢(xún)。如果散列函數(shù)設(shè)計(jì)的比較好的話(huà),數(shù)組的每個(gè)位置只有較少的值,并且浪費(fèi)空間也小。于是,查詢(xún)過(guò)程就是首先計(jì)算鍵的散列碼得到數(shù)組下標(biāo),然后內(nèi)存尋址(時(shí)間復(fù)雜度為O(1),賦值)找到數(shù)組的值,再遍歷list(時(shí)間復(fù)雜度為O(n),線(xiàn)性查詢(xún))即可。即hashCode和equals共同確定了對(duì)象的唯一性。
? ? ? ?所有類(lèi)都繼承于Object。Object的hashCode方法生成的散列碼,實(shí)際上是默認(rèn)使用對(duì)象的地址計(jì)算散列碼;而Object的equals方法實(shí)際上就是地址比較(==)。顯然,當(dāng)我們?cè)谑褂蒙⒘腥萜?如HashMap的Key,HashSet等)時(shí),我們自定義的類(lèi)中還繼承Object的hashCode和equals是不行的。必須重寫(xiě)hashCode和equals方法。好的hashCode()應(yīng)該產(chǎn)生分布均勻的散列碼。可以用IDE自動(dòng)生成。下面是一個(gè)例子:
1 import java.util.List; 2 3 public class Test9 { 4 5 boolean a; 6 byte b; 7 short c; 8 int d; 9 char e; 10 long f; 11 float g; 12 double h; 13 String i; 14 List<String> j; 15 int[] k; 16 17 @Override 18 public int hashCode() { 19 // [STEP1] hashCode()里的魔法數(shù)字,之所以選擇31,是因?yàn)樗莻€(gè)奇素?cái)?shù),如果乘數(shù)是偶數(shù),并且乘法溢出的話(huà),信息就會(huì)丟失,因?yàn)榕c2相乘等價(jià)于移位運(yùn)算。 20 // 使用素?cái)?shù)的好處并不是很明顯,但是習(xí)慣上都使用素?cái)?shù)來(lái)計(jì)算散列結(jié)果。31有個(gè)很好的特性,就是用移位和減法來(lái)代替乘法,可以得到更好的性能:31*i==(i<<5)-i。現(xiàn)在的VM可以自動(dòng)完成這種優(yōu)化。(from 《Effective Java》) 21 final int prime = 31; 22 // [STEP2] 為對(duì)象中每個(gè)有意義的域用下面公式計(jì)算散列碼 result = prime * result + c 23 int result = 1; 24 // boolean 25 result = prime * result + (a ? 1231 : 1237); 26 // byte/short/int/char 27 result = prime * result + b; 28 result = prime * result + c; 29 result = prime * result + d; 30 result = prime * result + e; 31 // long 32 result = prime * result + (int) (f ^ (f >>> 32)); 33 // float 34 result = prime * result + Float.floatToIntBits(g); 35 // double 36 long temp; 37 temp = Double.doubleToLongBits(h); 38 result = prime * result + (int) (temp ^ (temp >>> 32)); 39 // 對(duì)象 40 result = prime * result + ((i == null) ? 0 : i.hashCode()); 41 // List(要求每個(gè)元素實(shí)現(xiàn)hashCode) 42 result = prime * result + ((j == null) ? 0 : j.hashCode()); 43 // 數(shù)組(要求每個(gè)元素實(shí)現(xiàn)hashCode) 44 result = prime * result + Arrays.hashCode(k); 45 // [STEP3] 返回 46 return result; 47 } 48 @Override 49 public boolean equals(Object obj) { 50 if (this == obj) 51 return true; 52 if (obj == null) 53 return false; 54 if (getClass() != obj.getClass()) 55 return false; 56 Test9 other = (Test9) obj; 57 if (a != other.a) 58 return false; 59 if (b != other.b) 60 return false; 61 if (c != other.c) 62 return false; 63 if (d != other.d) 64 return false; 65 if (e != other.e) 66 return false; 67 if (f != other.f) 68 return false; 69 if (Float.floatToIntBits(g) != Float.floatToIntBits(other.g)) 70 return false; 71 if (Double.doubleToLongBits(h) != Double.doubleToLongBits(other.h)) 72 return false; 73 if (i == null) { 74 if (other.i != null) 75 return false; 76 } else if (!i.equals(other.i)) 77 return false; 78 if (j == null) { 79 if (other.j != null) 80 return false; 81 } else if (!j.equals(other.j)) 82 return false; 83 if (!Arrays.equals(k, other.k)) 84 return false; 85 return true; 86 } 87 }?
轉(zhuǎn)載于:https://www.cnblogs.com/storml/p/8550463.html
總結(jié)
以上是生活随笔為你收集整理的Java集合(7):散列与散列码的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java调用公安接口_src 公安部PG
- 下一篇: 人教版五年级计算机教案,人教版信息技术五