【Note-程序】HashMap-Integer,-V--SparseArray--

众所周知,基础数组的处理效率要比集合的处理效率高出指数倍(内存寻址优势,指哪打哪,直截了当)

在HashMap<K, V> 中K为Integer类型时,简单考虑,使用K作为数组下标可以使用基础数组替代HashMap,但这样处理的话会有一个问题,那就是K值较大时,直接使用数组会导致极大的内存空间浪费(很多数组内容都由null填充)——由此想到“稀疏数组”

SparseArray就是针对这一场景设计的
数组中仅仅保存有内容的空间 这样一来,就既可以利用数组高效的优势,又避免了内存空间的浪费。

取android.util.SparseArray源码中的put API如下:

/**
 * 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++;
    }
}

可以看到,在查找是否包含时使用了BinarySearch(二分搜索),在插入时又做了一次容量、size检查,有无用内存时手动gc,此gc为private函数,只是对内存进行了整理,无效内容置为null

查看DELETED定义:
private static final Object DELETED = new Object();
在删除时,只是将有效索引的内容至为DELETED,将mGarbage至为true,在下次有增/改操作时进行统一的容量整理;个人感觉这一api逻辑是经验设计,为的是避免连续删除时的频繁容量整理;

结论:

使用HashMap<Integer, V>时,用SparseArray替代,可以极大地提高性能

Powered by KyleCe

Copyright © 2015 - 2019 KyleCe All Rights Reserved.

访客数 : | 访问量 :