SimpleArrayMap 源码分析

SimpleArrayMap

SimpleArrayMap 是 Andorid V4 包提供的一种用来代替 HashMap 的数据结构,由于 HashMap 在数据容量过大时时间复杂度会越来与趋近于 O(N) , 故而效率不高。SimpleArrayMap 的实现方式和工作过程使其内存占用更小,在数据量不大时效率更高,所以在 Android 开发中我们可以择机选择适合的方式来实现 Map

下面我们就来一步步分析,为什么 SimpleArrayMap 可以实现更小的内存占用和更加高效查找

一、成员变量

/**
 * ArrayMap 扩容的最小数量
 */
private static final int BASE_SIZE = 4;

/**
 * 缓存数组的最大数量,使用小的缓存数组可以避免垃圾回收
 */
private static final int CACHE_SIZE = 10;

// 缓存所用的数组,以及已经换的数量
static Object[] mBaseCache;
static int mBaseCacheSize;
static Object[] mTwiceBaseCache;
static int mTwiceBaseCacheSize;

/**
 * 存放 key 的 hash 值的数组
 */
int[] mHashes;
/**
 * 存放 key 和 value 的数组
 */
Object[] mArray;
/**
 * 已存键值对的数量
 */
int mSize;

二、构造方法

/**
 * 创建容量为空的 mHashes 和 mArray 数组
 */
public SimpleArrayMap() {
    mHashes = ContainerHelpers.EMPTY_INTS;
    mArray = ContainerHelpers.EMPTY_OBJECTS;
    mSize = 0;
}

/**
 * 根据给定的初始容量创建 mHashes 和 mArray 数组
 */
public SimpleArrayMap(int capacity) {
    if (capacity == 0) {
        mHashes = ContainerHelpers.EMPTY_INTS;
        mArray = ContainerHelpers.EMPTY_OBJECTS;
    } else {
        allocArrays(capacity);
    }
    mSize = 0;
}

/**
 * 根据给定的 ArrayMap 初始化
 */
public SimpleArrayMap(SimpleArrayMap map) {
    this(); // 调用无参数构造函数
    if (map != null) {
        // 将给定的 ArrayMap 添加
        putAll(map); 
    }
}

/**
 * 将给定的 ArrayMap 添加本身
 */
public void putAll(SimpleArrayMap<? extends K, ? extends V> array) {
    final int N = array.mSize;

    // 确认容量支持添加给定的 ArrayMap
    ensureCapacity(mSize + N);

    if (mSize == 0) { // 如果原数组容量为 0,则将给定数组添加进新创建的数组中
        if (N > 0) {
            System.arraycopy(array.mHashes, 0, mHashes, 0, N);
            System.arraycopy(array.mArray, 0, mArray, 0, N<<1);
            mSize = N;
        }
    } else { // 如果原数组容量不为 0,则遍历给定数组,将给定数组的值添加到原数组中
        for (int i=0; i<N; i++) {
            put(array.keyAt(i), array.valueAt(i));
        }
    }
}

/**
 * 确认容量支持指定的最小数量,如果当前容量小于指定的数量,则以给定数量创建新的数组
 */
public void ensureCapacity(int minimumCapacity) {
    if (mHashes.length < minimumCapacity) {
        final int[] ohashes = mHashes;
        final Object[] oarray = mArray;

        // 以给定容量创建新的数组
        allocArrays(minimumCapacity); 
        if (mSize > 0) {
            System.arraycopy(ohashes, 0, mHashes, 0, mSize);
            System.arraycopy(oarray, 0, mArray, 0, mSize<<1);
        }

        // 缓存旧的 hash 数组
        freeArrays(ohashes, oarray, mSize); 
    }
}

SimpleArrayMap 有三个重载的构造方法,其中给定容量和给定 ArrayMap 的构造方法中涉及到的方法我们下面回一一解析

三、插入方法 put()

public V put(K key, V value) {
    final int hash;
    int index;
    if (key == null) {
        hash = 0;

        // 查找对应 key 在 hash 值数组中的位置
        index = indexOfNull();  
    } else {
        hash = key.hashCode();

        // 查找对应 key 在 hash 值数组中的位置
        index = indexOf(key, hash); 
    }

    if (index >= 0) { // 存在,直接替换 array 数组中对应位置的 value 值,并将旧值返回
        index = (index<<1) + 1;
        final V old = (V)mArray[index];
        mArray[index] = value;
        return old;
    }

    index = ~index; // 未找到情况,需要执行插入操作
    if (mSize >= mHashes.length) { // 为新插入数组需要扩容旧数组
        final int n = mSize >= (BASE_SIZE*2) ? (mSize+(mSize>>1)) // 当前键值对数量大于等于最小扩容数量的 2 倍时,n 等于 mSeze 的 1.5 倍
                : (mSize >= BASE_SIZE ? (BASE_SIZE*<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值