概述

  • ArrayMap和SparseArray都是基于二分查找实现的
  • ArrayMap的优势
    结构简单内存占用少,适用于小数据量的情况
  • SparseArray优势
    key值可以使基本类型,避免装箱开箱的消耗。
    无需hash,根据key值进行排序,二分查找

ArrayMap(适合少量数据情况下使用)

  • 继承自Map的 key- value的数据集合
  • 相比于HaspMap 它占用的内存较小,内存使用率更高,内部使用二分查找效率相对HaspMap要慢尤其是大量数据的时候。ArrayMap适合小数据量使用。
  • 内部有两个数组,一个用于存储hash值, 一个用于存储数据object。二分查找是根据hash值的大小排序的,因此,下图中的mHashes必定是一个有序的数据。因此它在增删的时候,会重新排序,效率低。
  • 二分查找和红黑树性能对比
  • 二分查找
    用数组保存数据,保证有序。二分查找速度很快,但是仅限于查找。因为插入的时候要保证有序,所以要往后移动数据以便插入。查找复杂度O(logn),插入复杂度O(n)
  • 红黑树
    无论数据量如何,插入删除时间复杂度都为O(logn)

SparseArray(适合key为基本类型,如int)

  • SparseArray稀疏数组,可以用来存储基本类型数据,避免数据的装箱拆箱,某些情况下性能更好。
  • 几个同类
  1. SparseArray
    存储Object类型,put(int key, E value)
  2. SparseIntArray
    存储int类型,put(int key, int value)
  3. SparseLongArray
    存储long类型,put(int key, long value)
  4. SparseBooleanArray
    存储boolen类型,put(int key, boolean value)
  • SparseArray用法
  • 添加数据
    put(int key, int value)
    append(int key, int value)
  • 删除数据
    removeAt(int index) 根据索引删除
    delete(int key) 根据键删除
    索引和键不同。
private fun test() {
        val intArray = SparseIntArray()
        intArray.put(1, 1)
        intArray.put(2, 2)
        intArray.put(3, 3)
        Log.d(TAG, "test: $intArray")
        intArray.delete(1)
        Log.d(TAG, "test: $intArray")
        intArray.removeAt(1)
        Log.d(TAG, "test: $intArray")
    }
D/MainActivity: test: {1=1, 2=2, 3=3}
D/MainActivity: test: {2=2, 3=3}
D/MainActivity: test: {2=2}
  • SparseArray特点
  1. 可以存储基本类型,避免装箱开箱
  2. 无需Hash
  3. 根据key进行排序
  4. 增加数据和查找数据基于二分查找
  5. 延迟删除
    并不是在每次remove操作直接移动数组元素,而是用一个删除标记将对应key的value标记为已删除,并标记需要回收,等待下次添加、扩容等需要移动数组元素的地方统一操作,进一步提升性能
  6. 某些场景下可以用SparseArray来代替HashMap<Integer, E>

参考资料