美文网首页Android学习
SparseArray 遍历及介绍

SparseArray 遍历及介绍

作者: BBNO | 来源:发表于2017-10-30 14:39 被阅读0次

    SparseArray 遍历

    方法1. 可以得到key值:

         SparseArray<UserBean> mUserArray = new SparseArray<>();
             //SparseArrayr容器的遍历方法1
            for (int i = 0; i < mUserArray.size(); i++) {
                int key = mUserArray.keyAt(i);
                UserBean user = mUserArray.get(key);
                Log.e("key = " + key, user.toString());
            }
    

    方法2. 不需要key值:

         SparseArray<UserBean> mUserArray = new SparseArray<>();
             //SparseArrayr容器的遍历方法2
            for (int i = 0; i < mUserArray.size(); i++) {
                UserBean user = mUserArray.valueAt(i);
                Log.e("没有key值", user.toString());
            }
    

    SparseArray 介绍

    首先说一下SparseArray是什么东西,在java中我们也没见过这个API啊,哦,原来是android中定义的一个类,按字面意思来说是一个稀疏数组,但通过源码注释我们发现它和数组有很大的区别:

     SparseArrays map integers to Objects.  Unlike a normal array of Objects,
    * there can be gaps in the indices.  It is intended to be more memory efficient
    * than using a HashMap to map Integers to Objects, both because it avoids
    * auto-boxing keys and its data structure doesn't rely on an extra entry object
    * for each mapping.
    

    我们通过这段注释大体知道,android希望我们用SparseArray在一些情况下代替HashMap来使用,因为它有更好的性能,大家都知道内存是非常宝贵的,尤其是在手机上。

    再看一下它的两个构造函数:

    /**
     * Creates a new SparseArray containing no mappings.
     */
    public SparseArray() {
        this(10);
    }
    
    /**
     * Creates a new SparseArray containing no mappings that will not
     * require any additional memory allocation to store the specified
     * number of mappings.  If you supply an initial capacity of 0, the
     * sparse array will be initialized with a light-weight representation
     * not requiring any additional array allocations.
     */
    public SparseArray(int initialCapacity) {
        if (initialCapacity == 0) {
            mKeys = EmptyArray.INT;
            mValues = EmptyArray.OBJECT;
        } else {
            mValues = ArrayUtils.newUnpaddedObjectArray(initialCapacity);
            mKeys = new int[mValues.length];
        }
        mSize = 0;
    }
    

    发现其默认的key-value数组大小是10,当然也可以是自定义的。

    SparseArray中有一些和HashMap中相似的实用方法,比如:

    put(int key, E value)
    get(int key)
    get(int key, E valueIfKeyNotFound)
    delete(int key)
    removeAt(int index)
    keyAt(int index)
    valueAt(int index)
    等等。
    

    随便分析一个方法,比如put(int key,E value):

    /**
     * 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) {
        int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
    
        if (i >= 0) {
            mValues[i] = value;
        } else {
            i = ~i;
    
            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++;
        }
    }
    

    代码中首先查询该key在SparseArray中是否已经存在,若存在,替换掉,若不存在,把对应的key和value插入到对应的数组中,然后mSize++。大家注意到在查询key时使用的折半查找,看源码:

    class ContainerHelpers {
    
        // 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
        }
    
        static int binarySearch(long[] array, int size, long value) {
            int lo = 0;
            int hi = size - 1;
    
            while (lo <= hi) {
                final int mid = (lo + hi) >>> 1;
                final long 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
        }
    }
    

    是不是我们在java中常用的一种查找方式。

    知道了这些之后,我们以后就可以使用SparseArray来代替HashMap了,但是要注意SparseArray中的key是int类型,若实际中不是int类型,还得乖乖的使用map,另外,根据key-value中的value类型不同,android又给封装了SparseIntArray,SparseBooleanArray,SparseLongArray等等,使用方法和SparseArray都大同小异,只要你会使用Map,那么你就会使用SparseArray。

    相关文章

      网友评论

        本文标题:SparseArray 遍历及介绍

        本文链接:https://www.haomeiwen.com/subject/kzbppxtx.html