HashMap在Android和Java中的不同實現

來源:互聯網
上載者:User

標籤:android   blog   http   io   ar   sp   for   java   on   

本篇文章轉載他人,原文地址:http://www.xyczero.com/blog/article/16/

起因

今天在項目中遇到一個很”奇葩”的問題。情況大致是這樣的:Android終端和伺服器(Spring),完全相同的字串索引值對放入 HashMap中竟然順序不一樣,這直接導致了伺服器和Android終端用HmacSHA256演算法加密出的摘要也不一樣,伺服器也就無法進行正確的數 據驗證。

然後帶著鬱悶的心情給程式加斷點進行原因尋找,發現原來是HashMap的中伺服器和終端雙方對於同樣的key存放順序竟然不一樣!

在HashCode產生衝突的情況下,不同的key在HashMap中存入的位置應該是相同的,即使在hashCode產生沖入,如果key-value put的順序相同,其存放的位置也應該是相同的。

尋找,解決

所以問題就應該出在HashMap上,只能去查看Java和Android關於HashMap的源碼了,發現兩者的hashCode()方法竟然不 一樣,小小激動了一下,可仔細一看,發現Android只是最佳化Java中的hashCode()方法,使其更加易於閱讀而已,但所運用的原理還是一樣 的,真是=。=。
具體代碼比較如下:

<!-- Android -->@Override public int hashCode() {    int hash = hashCode;    if (hash == 0) {        if (count == 0) {            return 0;        }        final int end = count + offset;        final char[] chars = value;        for (int i = offset; i < end; ++i) {            hash = 31*hash + chars[i];        }        hashCode = hash;    }    return hash;}<!-- Java-->public int hashCode() {    int h = hash;    int len = count;    if (h == 0 && len > 0) {        int off = offset;        char val[] = value;        for (int i = 0; i < len; i++) {            h = 31*h + val[off++];        }        hash = h;    }    return h;}

無奈,我只能繼續在源碼裡查看比較,最後發現原來是兩者的預設建構函式不一樣,本質上就是兩者的table大小不一樣,Java中的table預設 大小是16*0.75=12(容量 * 負載因子),而Android中table的預設大小是2,所以即使是同樣的字串按同樣的順序放入HashMap中它們的key值存放順序也會不一樣。

<!-- Android -->private static final Entry[] EMPTY_TABLE        = new HashMapEntry[MINIMUM_CAPACITY >>> 1];//預設建構函式public HashMap() {    table = (HashMapEntry<K, V>[]) EMPTY_TABLE;    threshold = -1; // Forces first put invocation to replace EMPTY_TABLE}<!-- Java -->static final int DEFAULT_INITIAL_CAPACITY = 16;static final float DEFAULT_LOAD_FACTOR = 0.75f;//預設建構函式public HashMap() {    this(DEFAULT_INITIAL_CAPACITY,DEFAULT_LOAD_FACTOR);}

其實仔細讀源碼會發現,在Android中所實現的HashMap類關於”閾值(threshold )”的設定也已經和Java不同了,具體請看截取的源碼:

<!-- Android -->//閾值固定取其table大小的3/4threshold = (newCapacity >> 1) + (newCapacity >> 2); <!-- Java -->//閾值取容量*負載因子或最大容量+1間的小值threshold = (int)Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
小結

所以總結來看HashMap在不同平台或不同語言中的實現細節是不一樣的,吃一塹,長一智,反正以後切記,牽扯到順序時HashMap真的不適合!

HashMap在Android和Java中的不同實現

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.