HashMap的長度為什么要是2的n次方


HashMap為了存取高效,要盡量較少碰撞,就是要盡量把數據分配均勻,每個鏈表長度大致相同,這個實現就在把數據存到哪個鏈表中的算法;
這個算法實際就是取模,hash%length,計算機中直接求余效率不如位移運算,源碼中做了優化hash&(length-1),
hash%length==hash&(length-1)的前提是length是2的n次方;
為什么這樣能均勻分布減少碰撞呢?2的n次方實際就是1后面n個0,2的n次方-1  實際就是n個1;
例如長度為9時候,3&(9-1)=0  2&(9-1)=0 ,都在0上,碰撞了;
例如長度為8時候,3&(8-1)=3  2&(8-1)=2 ,不同位置上,不碰撞;

 

其實就是按位“與”的時候,每一位都能  &1  ,也就是和1111……1111111進行與運算

 

0000 0011     3

& 0000 1000      8

= 0000 0000      0

 

 

0000 0010     2

& 0000 1000    8

= 0000 0000      0

 

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

 

0000 0011     3

& 0000 0111     7

= 0000 0011       3

 

 

0000 0010      2

& 0000 0111      7

= 0000 0010      2

 

 

當然如果不考慮效率直接求余即可(就不需要要求長度必須是2的n次方了);

 

 

有人懷疑兩種運算效率差別到底有多少,我做個測試:

[java]  view plain  copy
 
  1.     /** 
  2.      *  
  3.      * 直接【求余】和【按位】運算的差別驗證 
  4.      */  
  5. public static void main(String[] args) {  
  6.       
  7.     long currentTimeMillis = System.currentTimeMillis();  
  8.     int a=0;  
  9.     int times = 10000*10000;  
  10.     for (long i = 0; i < times; i++) {  
  11.          a=9999%1024;  
  12.     }  
  13.     long currentTimeMillis2 = System.currentTimeMillis();  
  14.       
  15.     int b=0;  
  16.     for (long i = 0; i < times; i++) {  
  17.          b=9999&(1024-1);  
  18.     }  
  19.       
  20.     long currentTimeMillis3 = System.currentTimeMillis();  
  21.     System.out.println(a+","+b);  
  22.     System.out.println("%: "+(currentTimeMillis2-currentTimeMillis));  
  23.     System.out.println("&: "+(currentTimeMillis3-currentTimeMillis2));  
  24. }  

 

 

 

結果:

783,783
%: 359
&: 93

 

 

 

 
 
版權聲明:本文為博主原創文章,未經博主允許不得轉載。 http://blog.csdn.net/sidihuo/article/details/78489820


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM