Java集合(7):散列與散列碼

來源:互聯網
上載者:User

標籤:cti   分布   body   線性   result   log   equals   import   array   

       散列的價值在於速度。我們使用數組來儲存鍵的資訊,這個資訊並不是鍵本身,而是通過鍵對象產生一個數字(散列碼),作為數組下標。由於數組的容量是固定的,而散列容器的大小是可變的,所以不同的鍵可以產生相同的數組下標(散列碼)。也就是說,可能會有衝突(當然也有特例,比如EnumMap和EnumSet)。所以,數組的值存放著一個儲存所有相同散列碼的值的list(引用)。然後對list中的值使用equals進行線性查詢。如果散列函數設計的比較好的話,數組的每個位置只有較少的值,並且浪費空間也小。於是,查詢過程就是首先計算鍵的散列碼得到數組下標,然後記憶體定址(時間複雜度為O(1),賦值)找到數組的值,再遍曆list(時間複雜度為O(n),線性查詢)即可。即hashCode和equals共同確定了對象的唯一性。

       所有類都繼承於Object。Object的hashCode方法產生的散列碼,實際上是預設使用對象的地址計算散列碼;而Object的equals方法實際上就是地址比較(==)。顯然,當我們在使用散列容器(如HashMap的Key,HashSet等)時,我們自訂的類中還繼承Object的hashCode和equals是不行的。必須重寫hashCode和equals方法。好的hashCode()應該產生分布均勻的散列碼。可以用IDE自動產生。下面是一個例子:

 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     @Override18     public int hashCode() {19         // [STEP1] hashCode()裡的魔法數字,之所以選擇31,是因為它是個奇素數,如果乘數是偶數,並且乘法溢出的話,資訊就會丟失,因為與2相乘等價於移位元運算。20         // 使用素數的好處並不是很明顯,但是習慣上都使用素數來計算散列結果。31有個很好的特性,就是用移位和減法來代替乘法,可以得到更好的效能:31*i==(i<<5)-i。現在的VM可以自動完成這種最佳化。(from 《Effective Java》)21         final int prime = 31;22         // [STEP2] 為對象中每個有意義的域用下面公式計算散列碼 result = prime * result + c23         int result = 1;24         // boolean25         result = prime * result + (a ? 1231 : 1237);26         // byte/short/int/char27         result = prime * result + b;28         result = prime * result + c;29         result = prime * result + d;30         result = prime * result + e;31         // long32         result = prime * result + (int) (f ^ (f >>> 32));33         // float34         result = prime * result + Float.floatToIntBits(g);35         // double36         long temp;37         temp = Double.doubleToLongBits(h);38         result = prime * result + (int) (temp ^ (temp >>> 32));39         // 對象40         result = prime * result + ((i == null) ? 0 : i.hashCode());41         // List(要求每個元素實現hashCode)42         result = prime * result + ((j == null) ? 0 : j.hashCode());43         // 數組(要求每個元素實現hashCode)44         result = prime * result + Arrays.hashCode(k);45         // [STEP3] 返回46         return result;47     }48     @Override49     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 }

 

Java集合(7):散列與散列碼

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.