赞
踩
参考:
其内部主要通过 2 个数组来存储 key 和 value,分别是 int[] 和 Object[]。这也限定了其 key 只能为 int 类型,且 key 不能重复,否则会发生覆盖。
一切操作都是基于二分查找算法,将 key 以升序的方法 “紧凑” 的排列在一起,从而提高内存的利用率以及访问的效率。相比较 HashMap 而言,这是典型的时间换空间的策略。
删除操作并不是真的删除,而只是标记为 DELETE,以便下次能够直接复用。
SparseArray
是android里为<Interger,Object>这样的Hashmap而专门写的类,目的是提高内存效率,其核心是折半二分查找函数(binarySearch)。
注意内存二字很重要,因为它仅仅提高内存效率,而不是提高执行效率,
它只适用于android系统(内存对android项目有多重要,地球人都知道)。
SparseArray有两个优点:
我们知道HashMap 采用一种所谓的“Hash 算法”来决定每个元素的存储位置,存放的都是数组元素的引用,通过每个对象的hash值来映射对象。而SparseArray则是用数组数据结构来保存映射,然后通过折半查找来找到对象。但其实一般来说,SparseArray执行效率比HashMap要慢一点,因为查找需要折半查找,而添加删除则需要在数组中执行,而HashMap都是通过外部映射。但相对来说影响不大,最主要是SparseArray不需要开辟内存空间来额外存储外部映射,从而节省内存。
//SparseArray public class SparseArray<E> implements Cloneable { private int[] mKeys; private Object[] mValues; private int mSize; public E get(int key, E valueIfKeyNotFound) { int i = ContainerHelpers.binarySearch(mKeys, mSize, key); if (i < 0 || mValues[i] == DELETED) { return valueIfKeyNotFound; } else { return (E) mValues[i]; } } } //SparseBooleanArray public class SparseBooleanArray implements Cloneable { private int[] mKeys; private boolean[] mValues; private int mSize; public boolean get(int key, boolean valueIfKeyNotFound) { int i = ContainerHelpers.binarySearch(mKeys, mSize, key); if (i < 0) { return valueIfKeyNotFound; } else { return mValues[i]; } } } //SparseIntArray public class SparseIntArray implements Cloneable { private int[] mKeys; private int[] mValues; private int mSize; public int get(int key, int valueIfKeyNotFound) { int i = ContainerHelpers.binarySearch(mKeys, mSize, key); if (i < 0) { return valueIfKeyNotFound; } else { return mValues[i]; } } } //SparseLongArray public class SparseLongArray implements Cloneable { private int[] mKeys; private long[] mValues; private int mSize; public long get(int key, long valueIfKeyNotFound) { int i = ContainerHelpers.binarySearch(mKeys, mSize, key); if (i < 0) { return valueIfKeyNotFound; } else { return mValues[i]; } } }
参考: ArrayMap详解及源码分析
mHashs 数组以升序的方式保存了所有的 hash code,在查找数据时则通过二分查找 hash code 所对应的 index。这也是它的 get() 比 HashMap 慢的根据原因所在。
通过 hash code 在 mHashs 数组里的 index 值来确定 key 以及 value 在 mArrays 数组中的存储位置。一般来说分别就是 index << 1 以及 index << 1 + 1。再简单点说就是 index * 2 以及 index * 2 + 1。
hashCode 必然可能存在冲突,这里是怎么解决的呢?简单点说就是,在 mHashs 中相邻地存多份 hash code,而在 mArray 中分别以它们的 index 来计算 key-value 的存储位置。
当进行 remove 操作时,在一定条件下,可能会发生数据的压缩,从而节省内存的使用。
public final class ArrayMap<K, V> implements Map<K, V> { int[] mHashes; Object[] mArray; int mSize; private static int binarySearchHashes(int[] hashes, int N, int hash) { try { return ContainerHelpers.binarySearch(hashes, N, hash); } catch (ArrayIndexOutOfBoundsException e) { if (CONCURRENT_MODIFICATION_EXCEPTIONS) { throw new ConcurrentModificationException(); } else { throw e; // the cache is poisoned at this point, there's not much we can do } } } }
package android.util; class ContainerHelpers { // This is Arrays.binarySearch(), but doesn't do any argument validation. static int binarySearch(int[] array, int size, int value) { int lo = 0; int hi = size - 1; while (lo <= hi) { final int mid = (lo + hi) >>> 1; final int midVal = array[mid]; if (midVal < value) { lo = mid + 1; } else if (midVal > value) { hi = mid - 1; } else { return mid; // value found } } return ~lo; // value not present } static int binarySearch(long[] array, int size, long value) { int lo = 0; int hi = size - 1; while (lo <= hi) { final int mid = (lo + hi) >>> 1; final long midVal = array[mid]; if (midVal < value) { lo = mid + 1; } else if (midVal > value) { hi = mid - 1; } else { return mid; // value found } } return ~lo; // value not present } }
1、如果key的类型已经确定为int类型,那么使用SparseArray,因为它避免了自动装箱的过程,
如果key为long类型,它还提供了一个LongSparseArray来确保key为long类型时的使用
2、如果key类型为其它的类型,则使用ArrayMap
//1、适用于键为int的map数据结构类型 //key为int的时候才能使用,注意是int而不是Integer, // 这也是sparseArray效率提升的一个点,去掉了装箱的操作 //2、适用于小规模数据存储 //3、内部使用二分查找进行数据查询,查询效率高 //4、不需要单独开辟内存来映射对象,节约内存 SparseArray<String> intSparseArray = new SparseArray<>(); intSparseArray.put(1, "java"); intSparseArray.put(2, "js"); intSparseArray.put(3, "kotlin"); intSparseArray.put(4, "flutter"); ArrayMap<String, String> arrayMap = new ArrayMap<>(); arrayMap.put("1", "java"); arrayMap.put("2", "js"); arrayMap.put("3", "kotlin"); arrayMap.put("4", "flutter"); HashMap<String, String> hashMap = new HashMap<>(); hashMap.put("1", "java"); hashMap.put("2", "js"); hashMap.put("3", "kotlin"); hashMap.put("4", "flutter");
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。