安卓開發-工具類的使用

SparseArray

中文名字是稀疏數組。

SparseArrays map integers to Objects. Unlike a normal array of Objects, there can be gaps in the indices. It is intended to be more efficient than using a HashMap to map Integers to Objects.

從它的源碼隨處可以看到,它採用了二分法(binarySearch)來存儲和查找數據。

看了上面一點資料之後,我並不認爲它的性能會比Hashmap的要好。hashmap畢竟能夠大約O(1)的時間查找到對象。而這個稀疏數組卻要二分才能找到目標。

-------------------------------

使用SparseArray有兩個好處。

1、使用hashmap的時候,我們需要這麼樣聲明:

HashMap<Integer, String> m=new HashMap<Integer, String>();

從上面這行代碼以看到,map中,將一個整數映射到一個Object的時候,是需要自動裝箱拆箱的(性能的浪費)。而SparseArray不需要。SparseArray的key直接就是int。

看key的聲明:

private int[] mKeys;

2、手持設備一般是內存受限的。Hashmap雖然查找性能好,但是map有一個問題就是浪費內存。而SparseArray雖然查找效率是O(logn)的,但是,,,,先看一下SparseArray的源碼中gc函數:

 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);
    }

這個函數“回收”SparseArray中已經“DELETED”的元素。設置它們爲NULL。從這點我們可以看到,SparseArray在刪除元素的時候,並不是真正的刪除。而是將相應的位置上置爲“DELETED”,然後在某個時間再去“gc”,設置爲null。這就是爲什麼SparseArray的api上描述,Unlike a normal array of Objects, there can be gaps in the indices,這些gaps就是gc的時候設置爲null的地方了。gc的時候,會將SparseArray中維護的數組內容向前移動(for語句中的那三句賦值操作)。這樣就把gaps消除了。每次gc,都能把之前設置爲DELETED的部分消除。那麼,數組後邊的元素移動到前面了,後面空出來的空間怎麼處理?從它源碼中也是隨處可看到這麼一句:

int n = ArrayUtils.idealIntArraySize(mSize + 1);

這句話就是分配數組大小。然後在put等添加操作的時候,用新申請的數組放置元素,原來的數組等待JVM來回收。

下面看一下idealIntArraySize函數的實現:

所以每次ArrayUtils分配數組大小的時候,會“酌情”考慮比need多分配一些空間。從而讓數組不是那麼容易就要因爲增加內容而再次分配空間。

-----------------------------------------------------

另外要注意的是,它是線程不安全的。

相對map來說,SparseArray能節省內存。

發佈了339 篇原創文章 · 獲贊 66 · 訪問量 236萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章