成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

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

Joyven / 2701人閱讀

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

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

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

1 為什么要用鏈表

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

2 代碼實(shí)現(xiàn) 1 put方法
 public V put(K key, V value) {
        //hash()散列函數(shù),主要作用通過一系列計(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;
        //查看對應(yīng)下標(biāo)是否有數(shù)據(jù),沒有數(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)化成紅黑樹之后
            else if (p instanceof TreeNode)
                e = ((TreeNode)p).putTreeVal(this, tab, hash, key, value);
            else {
                for (int binCount = 0; ; ++binCount) {
                    //判斷是不是鏈表最后一個節(jié)點(diǎn)
                    if ((e = p.next) == null) {
                        //發(fā)現(xiàn)是最后一個節(jié)點(diǎn)的話,添加在隊(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ù)組中對應(yīng)下標(biāo)數(shù)據(jù)
            //key相同 hash相同 數(shù)組中的對象就是我們要找的
            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相同的對象
                    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通過數(shù)組加鏈表的方式,實(shí)現(xiàn)了時間復(fù)雜度為O(1)的快速插入,查詢等操作,在平時使用中我們還可以通過指定數(shù)組大小來進(jìn)一步加快它的性能。
文章中只是寫了大概的思路,有不對的還請見諒!

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

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/72544.html

相關(guān)文章

  • 鄭方方打怪升級日記 — 初識HTML5與CSS3

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

    spademan 評論0 收藏0
  • 鄭方方打怪升級日記 — 初識HTML5與CSS3

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

    justCoding 評論0 收藏0
  • 鄭方方打怪升級日記 — 初識HTML5與CSS3

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

    jemygraw 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<