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 倍
                : (mSiz
在 Android 开发中,遇到 `SimpleArrayMap` could not resolve 的问题通常是因为开发环境未能正确识别该类。`SimpleArrayMap` 是 Android Support Library 中的一个高效替代 `HashMap` 的数据结构,适用于小数据量的键值对存储。 ### 常见原因及解决方法 #### 1. 缺少必要的依赖 确保项目中已正确引入包含 `SimpleArrayMap` 的支持库。它属于 v4 Support Library,因此需要在 `build.gradle` 文件中添加以下依赖: ```gradle implementation 'com.android.support:support-v4:28.0.0' ``` 版本号可根据实际需求调整,但建议使用较新版本以获得更好的兼容性和功能支持[^1]。 #### 2. 清理并重建项目 有时 Gradle 缓存可能导致类无法解析。尝试执行以下操作: - 点击菜单栏 **Build > Clean Project** - 接着点击 **Build > Rebuild Project** 这将清除所有中间文件并重新构建项目,有助于解决因缓存导致的问题。 #### 3. 检查导入语句 确认代码中是否正确导入了 `SimpleArrayMap` 类。正确的导入语句如下: ```java import android.support.v4.util.SimpleArrayMap; ``` 如果误用了其他包中的类似类(如 `android.util.SparseArray`),则会导致编译错误。 #### 4. 更新 Android Studio 和 Gradle 插件 确保使用的是最新版本的 Android Studio 和 Gradle 插件。旧版本可能存在兼容性问题或 Bug,导致某些类无法被正确识别。 在 `build.gradle` (Project-level) 中检查 Gradle 插件版本: ```gradle classpath 'com.android.tools.build:gradle:7.2.1' // 示例版本,请根据实际情况更新 ``` 同时,在 `gradle-wrapper.properties` 中确保使用了合适的 Gradle 版本: ```properties distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip ``` #### 5. 迁移至 AndroidX 如果你正在使用旧版 Support Library(即包名以 `android.support.v4` 开头),建议迁移到 AndroidX。Android 官方已全面转向 AndroidX,并停止对旧版 Support Library 的维护。 迁移步骤包括: - 在 `gradle.properties` 中启用 AndroidX: ```properties android.useAndroidX=true android.enableJetifier=true ``` - 使用 Android Studio 的自动迁移工具:**Refactor > Migrate to AndroidX** 迁移完成后,`SimpleArrayMap` 应从 `androidx.core.util` 包中导入: ```java import androidx.core.util.SimpleArrayMap; ``` #### 6. 同步项目与 Gradle 完成上述更改后,点击 **File > Sync Project with Gradle Files** 以确保所有配置生效。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值