Android之SparseArray

一.SparseArray概述

SparseArray是Android特有的API,Java中沒有此類荞膘,此類為Java容器中HashMap<Integer, E>的替代版本。相比于Java的HashMap,此類的優(yōu)點是更加節(jié)省內(nèi)存

二.SparseArray與HashMap的數(shù)據(jù)結(jié)構(gòu)對比

1.HashMap:

是數(shù)組和鏈表或者紅黑樹的結(jié)合體(至于具體什么時候是鏈表什么時候是紅黑樹以及HashMap的具體原理卿啡,這里就不再展開)昔瞧,下圖是HashMap的數(shù)據(jù)結(jié)構(gòu):

hashmap.png

2.SparseArray:

是單純的數(shù)組組合指蚁,通過key來映射數(shù)組下標(biāo)index,再通過數(shù)組下標(biāo)在value數(shù)組里查找自晰,下圖是SparseArray的數(shù)據(jù)結(jié)構(gòu):

sparsearray.png
下面來看看SparseArray的源碼:
數(shù)據(jù)結(jié)構(gòu)
    private int[] mKeys;
    private Object[] mValues;
    private int mSize;
二分查找函數(shù)
    // This is Arrays.binarySearch(), but doesn't do any argument validation.
    static int binarySearch(int[] array, int size, int value) {
        int lo = 0;
        int hi = size - 1;

        while (lo <= hi) {
            final int mid = (lo + hi) >>> 1;
            final int midVal = array[mid];

            if (midVal < value) {
                lo = mid + 1;
            } else if (midVal > value) {
                hi = mid - 1;
            } else {
                return mid;  // value found
            }
        }
        return ~lo;  // value not present
    }
put函數(shù)
    /**
     * Adds a mapping from the specified key to the specified value,
     * replacing the previous mapping from the specified key if there
     * was one.
     */
    public void put(int key, E value) {
        // 使用二分查找相應(yīng)的key凝化,成功返回數(shù)組的下標(biāo),失敗返回查找的最后一個位置的index再取反缀磕,之后插入新的數(shù)據(jù)是根據(jù)次數(shù)插入
        int i = ContainerHelpers.binarySearch(mKeys, mSize, key);

        if (i >= 0) {
            // 如果index大于0缘圈,表示查找成功,則更新相應(yīng)的value
            mValues[i] = value;
        } else {
            i = ~i;

            // 特殊的case袜蚕,直接存
            if (i < mSize && mValues[i] == DELETED) {
                mKeys[i] = key;
                mValues[i] = value;
                return;
            }

            if (mGarbage && mSize >= mKeys.length) {
                gc();

                // Search again because indices may have changed.
                i = ~ContainerHelpers.binarySearch(mKeys, mSize, key);
            }

            mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key);
            mValues = GrowingArrayUtils.insert(mValues, mSize, i, value);
            mSize++;
        }
    }
get函數(shù)
    /**
     * Gets the Object mapped from the specified key, or <code>null</code>
     * if no such mapping has been made.
     */
    public E get(int key) {
        return get(key, null);
    }

    /**
     * Gets the Object mapped from the specified key, or the specified Object
     * if no such mapping has been made.
     */
    @SuppressWarnings("unchecked")
    public E get(int key, E valueIfKeyNotFound) {
        int i = ContainerHelpers.binarySearch(mKeys, mSize, key);

        if (i < 0 || mValues[i] == DELETED) {
            return valueIfKeyNotFound;
        } else {
            return (E) mValues[i];
        }
    }
delete函數(shù)
    /**
     * Removes the mapping from the specified key, if there was any.
     */
    public void delete(int key) {
        int i = ContainerHelpers.binarySearch(mKeys, mSize, key);

        if (i >= 0) {
            // 標(biāo)記i的值為 DELETED
            if (mValues[i] != DELETED) {
                mValues[i] = DELETED;
                // 設(shè)置gc標(biāo)記為true
                mGarbage = true;
            }
        }
    }
gc函數(shù)
    // 遍歷一遍數(shù)組,將非DELETED資源全部移動到數(shù)組前面
    private void gc() {
        // Log.e("SparseArray", "gc start with " + mSize);

        int n = mSize;
        int o = 0;
        int[] keys = mKeys;
        Object[] values = mValues;

        for (int i = 0; i < n; i++) {
            Object val = values[i];

            if (val != DELETED) {
                if (i != o) {
                    keys[o] = keys[i];
                    values[o] = val;
                    values[i] = null;
                }

                o++;
            }
        }

        mGarbage = false;
        mSize = o;

        // Log.e("SparseArray", "gc end with " + mSize);
    }
總結(jié)

SparseArray的實現(xiàn)主要是使用兩個數(shù)組,一個來存儲key绢涡,另一個存儲value牲剃,兩者之間是通過index值來映射;增刪查改操作主要都是使用復(fù)雜度為O(logn)的二分查找來找到對應(yīng)的index再進行相應(yīng)的操作雄可。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末凿傅,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子数苫,更是在濱河造成了極大的恐慌聪舒,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件虐急,死亡現(xiàn)場離奇詭異箱残,居然都是意外死亡,警方通過查閱死者的電腦和手機止吁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門被辑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人敬惦,你說我怎么就攤上這事盼理。” “怎么了俄删?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵宏怔,是天一觀的道長。 經(jīng)常有香客問我畴椰,道長臊诊,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任迅矛,我火速辦了婚禮妨猩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘秽褒。我一直安慰自己壶硅,他們只是感情好威兜,可當(dāng)我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著庐椒,像睡著了一般椒舵。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上约谈,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天笔宿,我揣著相機與錄音,去河邊找鬼棱诱。 笑死泼橘,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的迈勋。 我是一名探鬼主播炬灭,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼靡菇!你這毒婦竟也來了重归?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤厦凤,失蹤者是張志新(化名)和其女友劉穎鼻吮,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體较鼓,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡椎木,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了笨腥。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拓哺。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖脖母,靈堂內(nèi)的尸體忽然破棺而出士鸥,到底是詐尸還是另有隱情,我是刑警寧澤谆级,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布烤礁,位于F島的核電站,受9級特大地震影響肥照,放射性物質(zhì)發(fā)生泄漏脚仔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一舆绎、第九天 我趴在偏房一處隱蔽的房頂上張望鲤脏。 院中可真熱鬧,春花似錦、人聲如沸猎醇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽硫嘶。三九已至阻问,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間沦疾,已是汗流浹背称近。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留哮塞,地道東北人刨秆。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像忆畅,于是被迫代替她去往敵國和親坛善。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,754評論 25 707
  • 一剔交、基本數(shù)據(jù)類型 注釋 單行注釋:// 區(qū)域注釋:/* */ 文檔注釋:/** */ 數(shù)值 對于byte類型而言...
    龍貓小爺閱讀 4,257評論 0 16
  • HashMap 是 Java 面試必考的知識點肆饶,面試官從這個小知識點就可以了解我們對 Java 基礎(chǔ)的掌握程度。網(wǎng)...
    野狗子嗷嗷嗷閱讀 6,661評論 9 107
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法岖常,類相關(guān)的語法驯镊,內(nèi)部類的語法,繼承相關(guān)的語法竭鞍,異常的語法板惑,線程的語...
    子非魚_t_閱讀 31,598評論 18 399
  • 人的價值的高低是不能以金錢來衡量的,有的行業(yè)金錢是衡量努力程度的標(biāo)準(zhǔn)偎快,可有的行業(yè)無論多么努力創(chuàng)造的價值多高也不會有...
    吳shirley閱讀 1,331評論 0 0