1. 程式人生 > >HashMap的putVal函式原始碼解析

HashMap的putVal函式原始碼解析

    /**
     * The default initial capacity - MUST be a power of two.
     */
    // 預設容量16
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

    /**
     * The load factor used when none specified in constructor.
     */
    // 預設載入因子
    // 如果size大於載入因子*容量,將擴容resize()
    static final float DEFAULT_LOAD_FACTOR = 0.75f;

put呼叫的是putVal

    /**
     * Associates the specified value with the specified key in this map.
     * If the map previously contained a mapping for the key, the old
     * value is replaced.
     *
     * @param key key with which the specified value is to be associated
     * @param value value to be associated with the specified key
     * @return the previous value associated with <tt>key</tt>, or
     *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
     *         (A <tt>null</tt> return can also indicate that the map
     *         previously associated <tt>null</tt> with <tt>key</tt>.)
     */
    public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }

putVal

   /**
     * Implements Map.put and related methods
     *
     * @param hash hash for key
     * @param key the key
     * @param value the value to put
     * @param onlyIfAbsent if true, don't change existing value
     * @param evict if false, the table is in creation mode.
     * @return previous value, or null if none
     */
    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i;
        // 判斷HashMap的Node陣列是否為空
        if ((tab = table) == null || (n = tab.length) == 0)
            // 如果為空,則初始化陣列
            n = (tab = resize()).length;
        // 判斷HashMap的Node陣列的hash位置是否為空
        if ((p = tab[i = (n - 1) & hash]) == null)
            // 如果為空直接插入一個節點
            tab[i] = newNode(hash, key, value, null);
        // 如果不為空
        else {
            Node<K,V> e; K k;
            // 當前Node的Key和新插入的Key是否相等
            if (p.hash == hash &&
                    ((k = p.key) == key || (key != null && key.equals(k))))
                // 直接覆蓋
                e = p;
            // 當前Node是否為紅黑樹的TreeNode
            else if (p instanceof TreeNode)
                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
            // 當前Node是否為單向連結串列的Node
            else {
                // 遍歷單向連結串列
                for (int binCount = 0; ; ++binCount) {
                    if ((e = p.next) == null) {
                        p.next = newNode(hash, key, value, null);
                        // 如果雜湊衝突(雜湊碰撞)的數量大於等於8,將單向連結串列轉換為紅黑樹
                        // 當執行treeifyBin(tab, hash);的時候,也不一定必須轉換成紅黑樹
                        // 如果一個Node的單向連結串列的長度小於64,擴容
                        // 如果一個Node的單向連結串列的長度大於等於64,才將此單向連結串列轉換成紅黑樹
                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            treeifyBin(tab, hash);
                        break;
                    }
                    // 當前Node的Key和新插入的Key是否相等
                    if (e.hash == hash &&
                            ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    p = e;
                }
            }
            // 判斷新插入的Node是否已存在,如果已存在根據onlyIfAbsent是否用新值覆蓋舊值
            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;
    }

相關推薦

HashMap的putVal函式原始碼解析

/** * The default initial capacity - MUST be a power of two. */ // 預設容量16 static final int DEFAULT_INITIAL_CAPACITY

jQuery原始碼解析:變數與函式

 //原始碼剖析都基於jQuery-2.0.3版本,主要考慮到相容IE 2行:jQuery javaScript Library v2.0.3——jQuery版本 3行:http://jQuery.com——官網 5~6行:Includes Sizzle.js;http://sizzlejs.

redis原始碼解析(二)動態字串sds基本功能函式

1. 簡介   本文繼上文基礎上,分析動態字串的功能函式,位於sds.c。由於函式較多,本篇介紹實現動態變化的基本增刪新建釋放函式。 2. 原始碼分析   sdsHdrSize()函式用於返回sdshdr的大小,主要使用sizeof()函式實現。 /*返回sds

Java原始碼解析HashMap的tableSizeFor函式

aka,HashMap的容量大小必須為2的指數,即16,32,64,128這樣的值。那麼,在建構函式中,如果呼叫者指定了HashMap的初始大小不是2的指數,那麼,HashMap的tableSizeFor函式,會計算一個大於或等於給定引數的2的指數的值。先來看一下tableSizeFor函式的原始碼

underscore.js原始碼解析函式繫結

1. 引言   underscore.js是一個1500行左右的Javascript函式式工具庫,裡面提供了很多實用的、耦合度極低的函式,用來方便的操作Javascript中的陣列、物件和函式,它支援函式式和麵向物件鏈式的程式設計風格,還提供了一個精巧的模板引

Spring原始碼解析——從XmlBeanFactory的建構函式開始看LoadBeanDefinitions

        之前的文章聊過ClassPathResource類,通過這個類,我們從classpath載入到了我們的spring配置檔案,之後,就開始執行XmlBeanFactory的構造過程了:public XmlBeanFactory(Resource resource

Spring IOC原理原始碼解析(@Autowired原理詳解 :標識建構函式)(一 )

IOC,inversion of control 控制反轉,有時候也叫DI,dependency injection 依賴注入,是一種程式碼解耦的方式。 在一個類中定義一個屬性,正常情況下需要在此類中有對此屬性賦值的程式碼,如setter方法,或者在建構函式中

原始碼解析: Imread函式

在第一篇處,我們只是在最表層的上面操作函式,當別人問我們時,我們其實什麼也不知道的。就知道,imread是讀取函數了,然後掉用其它的函式的樂樂。當然,上面我們可以好好學習人家為什麼要這樣做了!這裡,看一個函式finddecoder()。這個函式主要是獲取decoder物件,從而決定讀取什麼樣字尾名的影象(j

caffe原始碼解析之cblas函式

Y(vetor)←αAX + βY This function multiplies A * X (after transposing A, if needed) and multiplies the resulting matrix by alpha. It then multiplies vector

pinpoint 原始碼解析,怎樣監控tornado 協程中的函式

## 協程中監控函式,為啥比較特殊! 首先需要明白pinpoint 怎樣做監控的。 1. python中通過包裝器,實現函式/方法包裝 2. pinpoint內部維持一個呼叫棧的關係,內部通過棧來實現。這個棧的生命期和函式執行的生命期繫結在一起。 然而, 協程函式可以被yeild,await 中斷。

yolo v2 損失函式原始碼解讀

前提說明:     1, 關於 yolo 和 yolo v2 的詳細解釋請移步至如下兩個連結,或者直接看論文(我自己有想寫 yolo 的教程,但思前想後下面兩個連結中的文章質量實在是太好了_(:з」∠)_)         yo

Netty進階:Futrue&Promise原始碼解析

文章目錄 1. Future&Promise 2. AbstractFuture 3.Completefuture 4.Channelfuture&Completechannel

大資料基礎(1)zookeeper原始碼解析

五 原始碼解析   public enum ServerState { LOOKING, FOLLOWING, LEADING, OBSERVING;}zookeeper伺服器狀態:剛啟動LOOKING,follower是FOLLOWING,leader是LEADING,observer是

Android框架原始碼解析之(四)Picasso

這次要分析的原始碼是 Picasso 2.5.2 ,四年前的版本,用eclipse寫的,但不影響這次我們對其原始碼的分析 地址:https://github.com/square/picasso/tree/picasso-parent-2.5.2 Picasso的簡單使用

Android框架原始碼解析之(三)ButterKnife

注:所有分析基於butterknife:8.4.0 原始碼目錄:https://github.com/JakeWharton/butterknife 其中最主要的3個模組是: Butterknife註解處理器https://github.com/JakeWharton/

Android框架原始碼解析之(二)OKhttp

原始碼在:https://github.com/square/okhttp 包實在是太多了,OKhttp核心在這塊https://github.com/square/okhttp/tree/master/okhttp 直接匯入Android Studio中即可。 基本使用:

Android框架原始碼解析之(一)Volley

前幾天面試CVTE,HR面掛了。讓內部一個學長幫我查看了一下面試官評價,發現二面面試官的評價如下: 廣度OK,但缺乏深究能力,深度與實踐不足 原始碼:只能說流程,細節程式碼不清楚,retrofit和volley都是。 感覺自己一方面:自己面試技巧有待提高吧(框

HashMap原始碼解析(JDK8)

前言 這段時間有空,專門填補了下基礎,把常用的ArrayList、LinkedList、HashMap、LinkedHashMap、LruCache原始碼看了一遍,List相對比較簡單就不單獨介紹了,Map準備用兩篇的篇幅,分別介紹HashMap和(LruCache+LinkedHa

原始碼解析--Long、long型別的比較遇到的問題

Long、long型別的比較遇到的問題: 1、long 是基本型別 Long是物件型別。 public static void main(String[] args) { Long A = 127l; Long B = 127l; long C = 127; l

CopyOnWriteArrayList實現原理以及原始碼解析

CopyOnWriteArrayList實現原理以及原始碼解析 1、CopyOnWrite容器(併發容器) Copy-On-Write簡稱COW,是一種用於程式設計中的優化策略。 其基本思路是,從一開始大家都在共享同一個內容,當某個人想要修改這個內容的時候,才