成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

HashMap實(shí)現(xiàn)思路(小白科普)

Joyven / 2658人閱讀

摘要:數(shù)據(jù)結(jié)構(gòu)小白科普是和中常用的一個(gè)容器,采用了數(shù)組鏈表的結(jié)構(gòu)來(lái)存儲(chǔ)數(shù)據(jù)新增紅黑樹(shù),當(dāng)鏈表長(zhǎng)度大于以后,鏈表會(huì)進(jìn)化成紅黑樹(shù)。下面具體分析的實(shí)現(xiàn)思路。

Android 數(shù)據(jù)結(jié)構(gòu) java 小白科普

HashMap是java和Android中常用的一個(gè)容器,采用了數(shù)組+鏈表的結(jié)構(gòu)來(lái)存儲(chǔ)數(shù)據(jù)(PS:jdk1.8新增紅黑樹(shù),當(dāng)鏈表長(zhǎng)度大于8以后,鏈表會(huì)進(jìn)化成紅黑樹(shù))。下面具體分析HashMap的實(shí)現(xiàn)思路。

1 為什么要用鏈表

很多人疑惑,實(shí)現(xiàn)HashMap直接用數(shù)組不就可以了嗎,通過(guò)hash函數(shù)計(jì)算出key對(duì)應(yīng)的數(shù)組的下標(biāo),value直接存進(jìn)去。為什么會(huì)用鏈表呢?
問(wèn)題的關(guān)鍵就出在hash函數(shù)身上,因?yàn)榈浆F(xiàn)在為止還沒(méi)有出現(xiàn)一種一個(gè)不同的key對(duì)應(yīng)的hash值都不一樣的函數(shù),(包括MD5,SHA等算法),假如a,b兩個(gè)key通過(guò)hash函數(shù)得到的數(shù)組下標(biāo)都是1,a已經(jīng)存進(jìn)數(shù)組下標(biāo)為1的位置,b該怎么存儲(chǔ)呢?把a(bǔ)對(duì)應(yīng)的value刪了,替換成b對(duì)應(yīng)的value?這種作法顯然是不可取的。所以在HashMap中引入了鏈表,還是a,b兩個(gè)key,存儲(chǔ)a的時(shí)候,我們先判斷下數(shù)組下標(biāo)為1的位置是否有數(shù)據(jù),如果沒(méi)有直接插入數(shù)組中,這時(shí)候a對(duì)應(yīng)的value插入到了數(shù)組中,這時(shí)候我們來(lái)存儲(chǔ)b,我們發(fā)現(xiàn)下標(biāo)為1的位置已經(jīng)存了數(shù)據(jù),我們用a.next來(lái)指向b,形成一個(gè)鏈表。以此類(lèi)推。

2 代碼實(shí)現(xiàn) 1 put方法
 public V put(K key, V value) {
        //hash()散列函數(shù),主要作用通過(guò)一系列計(jì)算,得出應(yīng)存在數(shù)組的下標(biāo)
        return putVal(hash(key), key, value, false, true);
 }
  final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node[] tab; Node p; int n, i;
        if ((tab = table) == null || (n = tab.length) == 0)
        //擴(kuò)容數(shù)據(jù)搬遷
            n = (tab = resize()).length;
        //查看對(duì)應(yīng)下標(biāo)是否有數(shù)據(jù),沒(méi)有數(shù)據(jù)直接插入數(shù)據(jù)
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
        else {
            Node e; K k;
            //key相等
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;
             //進(jìn)化成紅黑樹(shù)之后
            else if (p instanceof TreeNode)
                e = ((TreeNode)p).putTreeVal(this, tab, hash, key, value);
            else {
                for (int binCount = 0; ; ++binCount) {
                    //判斷是不是鏈表最后一個(gè)節(jié)點(diǎn)
                    if ((e = p.next) == null) {
                        //發(fā)現(xiàn)是最后一個(gè)節(jié)點(diǎn)的話(huà),添加在隊(duì)尾
                        p.next = newNode(hash, key, value, null);
                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            treeifyBin(tab, hash);
                        break;
                    }
                    //key相等
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    p = e;
                }
            }
            //重新賦值
            if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }
        }
        ++modCount;
        if (++size > threshold)
            resize();
        afterNodeInsertion(evict);
        return null;
    }
2 get方法
 public V get(Object key) {
        Node e;
        return (e = getNode(hash(key), key)) == null ? null : e.value;
}
final Node getNode(int hash, Object key) {
        Node[] tab; Node first, e; int n; K k;
        if ((tab = table) != null && (n = tab.length) > 0 &&
            (first = tab[(n - 1) & hash]) != null) {//取出數(shù)組中對(duì)應(yīng)下標(biāo)數(shù)據(jù)
            //key相同 hash相同 數(shù)組中的對(duì)象就是我們要找的
            if (first.hash == hash && // always check first node
                ((k = first.key) == key || (key != null && key.equals(k))))
                return first;
            if ((e = first.next) != null) {
                if (first instanceof TreeNode)
                    return ((TreeNode)first).getTreeNode(hash, key);
                do {
                //循環(huán)遍歷 找到key相同的對(duì)象
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        return e;
                } while ((e = e.next) != null);
            }
        }
        return null;
}
3 總結(jié)

HashMap通過(guò)數(shù)組加鏈表的方式,實(shí)現(xiàn)了時(shí)間復(fù)雜度為O(1)的快速插入,查詢(xún)等操作,在平時(shí)使用中我們還可以通過(guò)指定數(shù)組大小來(lái)進(jìn)一步加快它的性能。
文章中只是寫(xiě)了大概的思路,有不對(duì)的還請(qǐng)見(jiàn)諒!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/72544.html

相關(guān)文章

  • 鄭方方打怪升級(jí)日記 — 初識(shí)HTML5與CSS3

    摘要:任務(wù)名稱(chēng)響應(yīng)式砸蛋頁(yè)面任務(wù)背景前輩方方啊最近項(xiàng)目也沒(méi)什么事情你看這個(gè)砸蛋頁(yè)面不是很好看要不你做一個(gè)響應(yīng)式砸蛋頁(yè)面吧系統(tǒng)鄭方方接下前輩的任務(wù)鄭方方自動(dòng)解析任務(wù)步驟任務(wù)響應(yīng)式砸蛋頁(yè)面與入門(mén)閱讀秘籍響應(yīng)式布局制作層搭配搭配控制器完成任務(wù)人物背 任務(wù)名稱(chēng):響應(yīng)式砸蛋頁(yè)面 任務(wù)背景 前輩:方方啊,最近項(xiàng)目也沒(méi)什么事情,你看這個(gè)砸蛋頁(yè)面不是很好看,要不你做一個(gè)響應(yīng)式砸蛋頁(yè)面吧? 系統(tǒng):鄭方方接下前...

    spademan 評(píng)論0 收藏0
  • 鄭方方打怪升級(jí)日記 — 初識(shí)HTML5與CSS3

    摘要:任務(wù)名稱(chēng)響應(yīng)式砸蛋頁(yè)面任務(wù)背景前輩方方啊最近項(xiàng)目也沒(méi)什么事情你看這個(gè)砸蛋頁(yè)面不是很好看要不你做一個(gè)響應(yīng)式砸蛋頁(yè)面吧系統(tǒng)鄭方方接下前輩的任務(wù)鄭方方自動(dòng)解析任務(wù)步驟任務(wù)響應(yīng)式砸蛋頁(yè)面與入門(mén)閱讀秘籍響應(yīng)式布局制作層搭配搭配控制器完成任務(wù)人物背 任務(wù)名稱(chēng):響應(yīng)式砸蛋頁(yè)面 任務(wù)背景 前輩:方方啊,最近項(xiàng)目也沒(méi)什么事情,你看這個(gè)砸蛋頁(yè)面不是很好看,要不你做一個(gè)響應(yīng)式砸蛋頁(yè)面吧? 系統(tǒng):鄭方方接下前...

    justCoding 評(píng)論0 收藏0
  • 鄭方方打怪升級(jí)日記 — 初識(shí)HTML5與CSS3

    摘要:任務(wù)名稱(chēng)響應(yīng)式砸蛋頁(yè)面任務(wù)背景前輩方方啊最近項(xiàng)目也沒(méi)什么事情你看這個(gè)砸蛋頁(yè)面不是很好看要不你做一個(gè)響應(yīng)式砸蛋頁(yè)面吧系統(tǒng)鄭方方接下前輩的任務(wù)鄭方方自動(dòng)解析任務(wù)步驟任務(wù)響應(yīng)式砸蛋頁(yè)面與入門(mén)閱讀秘籍響應(yīng)式布局制作層搭配搭配控制器完成任務(wù)人物背 任務(wù)名稱(chēng):響應(yīng)式砸蛋頁(yè)面 任務(wù)背景 前輩:方方啊,最近項(xiàng)目也沒(méi)什么事情,你看這個(gè)砸蛋頁(yè)面不是很好看,要不你做一個(gè)響應(yīng)式砸蛋頁(yè)面吧? 系統(tǒng):鄭方方接下前...

    jemygraw 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<