返回

SparseArray,一个高效的 Android 数据结构

Android

SparseArray 是一种数据结构,专为优化 Android 应用程序中的稀疏数据集合而设计。它比标准的数组或映射更有效率,因为它只存储有值的索引和值,而不存储所有可能的索引。这意味着它可以在内存使用量和检索速度方面带来显著的节省。

SparseArray 的优点

  • 内存效率: 只存储非空值的索引和值,而不是所有可能的索引。
  • 快速查找: 通过索引直接访问元素,无需遍历整个数组或映射。
  • 易于使用: 简单的 API,类似于标准的数组或映射。

SparseArray 的缺点

  • 插入顺序丢失: SparseArray 不会保留元素的插入顺序。
  • 可能产生碎片: 删除元素可能会导致内存碎片,从而降低性能。

SparseArray 的应用场景

SparseArray 非常适合存储稀疏数据集合,例如:

  • 稀疏列表或映射
  • 缓存
  • 稀疏矩阵
  • 稀疏索引

SparseArray 的源码解析

构造方法

public SparseArray() {
    this(10);
}

public SparseArray(int initialCapacity) {
    if (initialCapacity == 0) {
        mKeys = EMPTY_INT_ARRAY;
        mValues = EMPTY_OBJECT_ARRAY;
    } else {
        mKeys = new int[initialCapacity];
        mValues = new Object[initialCapacity];
    }
    mSize = 0;
}

SparseArray 的构造方法允许指定初始容量。如果没有指定容量,则使用默认容量 10。如果初始容量为 0,则创建空数组。否则,创建指定容量的新数组。

常用 API

  • put(int key, Object value) :将指定值与指定键关联。
  • get(int key) :返回与指定键关联的值。
  • remove(int key) :移除与指定键关联的元素。
  • size() :返回 SparseArray 中元素的数量。

public void put(int key, Object value) {
    int i = ContainerHelpers.binarySearch(mKeys, mSize, key);

    if (i < 0) {
        i = ~i;

        if (mSize >= mKeys.length) {
            int[] nkeys = new int[mSize + (mSize < 12 ? 8 : (mSize >> 1))];
            Object[] nvalues = new Object[mSize + (mSize < 12 ? 8 : (mSize >> 1))];

            System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
            System.arraycopy(mValues, 0, nvalues, 0, mValues.length);

            mKeys = nkeys;
            mValues = nvalues;
        }

        if (mSize == i) {
            mKeys[i] = key;
            mValues[i] = value;
            ++mSize;
            return;
        }

        System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
        System.arraycopy(mValues, i, mValues, i + 1, mSize - i);

        mKeys[i] = key;
        mValues[i] = value;
        ++mSize;
    } else {
        mValues[i] = value;
    }
}

put() 方法使用二分查找找到指定键的位置。如果键不存在,则插入键和值。如果键存在,则更新值。

public void remove(int key) {
    int i = ContainerHelpers.binarySearch(mKeys, mSize, key);

    if (i >= 0) {
        System.arraycopy(mKeys, i + 1, mKeys, i, mSize - (i + 1));
        System.arraycopy(mValues, i + 1, mValues, i, mSize - (i + 1));
        --mSize;
    }
}

remove() 方法使用二分查找找到指定键的位置。如果键存在,则删除该键及其关联的值。

public void put(int key, Object value) {
    int i = ContainerHelpers.binarySearch(mKeys, mSize, key);

    if (i < 0) {
        i = ~i;
        ... // 省略其他代码
    } else {
        mValues[i] = value;
    }
}

put() 方法还可用于更新现有键的值。如果键存在,则更新值。

public Object get(int key) {
    int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
    return i < 0 ? null : mValues[i];
}

get() 方法使用二分查找找到指定键的位置。如果键存在,则返回关联的值。否则,返回 null。