• Android 移动端数据结构


    ## SparseArray 

    ## SparseBooleanArray

    ## SparseIntArray

    ## SparseLongArray

    * 位于android.util,Android 中的数据结构,针对移动端做了优化,在数据量比较少的情况下,性能会好过 HashMap,类似于 HashMap,key:int ,value:object 。

    * 为什么性能会好:

    1. key  和 value  采用数组进行存储。存储 key 的数组是 int 类型,不需要进行装箱操作。提供了速度。

    2. 采用二分查找法,在插入进行了排序,所以两个数组是按照从小到大进行排序的。

    3. 在查找的时候,进行二分查找,数据量少的情况下,速度比较快。

    同时还有一个类:SparseArrayCompat,位于android.support.v4.util,与 SparseArray 一样的。

    其中有好几个类似的数据结构:SparseBooleanArray(key:int, value:boolean), SparseIntArray(key:int, value:int), SparseLongArray(key:int, value:long). SparseArray 通过数组对 key , value 进行存储。

    在 map Integers to Objects 方面进行了优化,所以比使用 HashMap 提高了性能,建议遇到key:int, value:object 的情况下使用。

    构造方法:

    默认构造方法中会创建长度为 10 的数组来分别储存 key 和 value。

    可以自己在手动输入一个数字,来创建一个指定长度的数组来存储key 和 value。

    增:

    public void put(int key, E value)  // 存储指定key 和指定value ,假如指定key 已经有了在映射中,替换掉已经存在的。
    public void append(int key, E value) // 储存 key value 到数组,key 的索引应该大于数组中的已有索引

    删:

    public void delete(int key)  // 删除指定key
    public void remove(int key)  // 调用 delete 方法
    public void removeAt(int index) // 删除指定索引
    public void removeAtRange(int index, int size) //删除指定范围的索引
    public void clear()  //清空所有内容

    改:

    public void put(int key, E value)  // 指定key 已存在的情况下,更新,不存在的情况下,增加
    public void setValueAt(int index, E value) // 更新指定索引的 value

    查:

    public E get(int key)   // 得到指定key 的 value,调用的是 get(int key, null)
    public E get(int key, E valueIfKeyNotFound) // 返回指定key 的value,没有的情况下,返回传入的默认值
    public int indexOfKey(int key) // 传入key 的索引
    public int indexOfValue(E value) // 传入 value 的索引
    public int keyAt(int index) // 指定索引的 key
    public E valueAt(int index) //指定索引的 value

    源码:

      1 public class SparseArray<E> implements Cloneable {
      2     private static final Object DELETED = new Object();
      3     private boolean mGarbage = false;
      4 
      5     private int[] mKeys;
      6     private Object[] mValues;
      7     private int mSize;
      8 
      9     /**
     10      * Creates a new SparseArray containing no mappings.
     11      */
     12     public SparseArray() {
     13         this(10);
     14     }
     15 
     16     /**
     17      * Creates a new SparseArray containing no mappings that will not
     18      * require any additional memory allocation to store the specified
     19      * number of mappings.  If you supply an initial capacity of 0, the
     20      * sparse array will be initialized with a light-weight representation
     21      * not requiring any additional array allocations.
     22      */
     23     public SparseArray(int initialCapacity) {
     24         if (initialCapacity == 0) {
     25             mKeys = EmptyArray.INT;
     26             mValues = EmptyArray.OBJECT;
     27         } else {
     28             mValues = ArrayUtils.newUnpaddedObjectArray(initialCapacity);
     29             mKeys = new int[mValues.length];
     30         }
     31         mSize = 0;
     32     }
     33 
     34     @Override
     35     @SuppressWarnings("unchecked")
     36     public SparseArray<E> clone() {
     37         SparseArray<E> clone = null;
     38         try {
     39             clone = (SparseArray<E>) super.clone();
     40             clone.mKeys = mKeys.clone();
     41             clone.mValues = mValues.clone();
     42         } catch (CloneNotSupportedException cnse) {
     43             /* ignore */
     44         }
     45         return clone;
     46     }
     47 
     48     /**
     49      * Gets the Object mapped from the specified key, or <code>null</code>
     50      * if no such mapping has been made.
     51      */
     52     public E get(int key) {
     53         return get(key, null);
     54     }
     55 
     56     /**
     57      * Gets the Object mapped from the specified key, or the specified Object
     58      * if no such mapping has been made.
     59      */
     60     @SuppressWarnings("unchecked")
     61     public E get(int key, E valueIfKeyNotFound) {
     62         int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
     63 
     64         if (i < 0 || mValues[i] == DELETED) {
     65             return valueIfKeyNotFound;
     66         } else {
     67             return (E) mValues[i];
     68         }
     69     }
     70 
     71     /**
     72      * Removes the mapping from the specified key, if there was any.
     73      */
     74     public void delete(int key) {
     75         int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
     76 
     77         if (i >= 0) {
     78             if (mValues[i] != DELETED) {
     79                 mValues[i] = DELETED;
     80                 mGarbage = true;
     81             }
     82         }
     83     }
     84 
     85     /**
     86      * @hide
     87      * Removes the mapping from the specified key, if there was any, returning the old value.
     88      */
     89     public E removeReturnOld(int key) {
     90         int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
     91 
     92         if (i >= 0) {
     93             if (mValues[i] != DELETED) {
     94                 final E old = (E) mValues[i];
     95                 mValues[i] = DELETED;
     96                 mGarbage = true;
     97                 return old;
     98             }
     99         }
    100         return null;
    101     }
    102 
    103     /**
    104      * Alias for {@link #delete(int)}.
    105      */
    106     public void remove(int key) {
    107         delete(key);
    108     }
    109 
    110     /**
    111      * Removes the mapping at the specified index.
    112      */
    113     public void removeAt(int index) {
    114         if (mValues[index] != DELETED) {
    115             mValues[index] = DELETED;
    116             mGarbage = true;
    117         }
    118     }
    119 
    120     /**
    121      * Remove a range of mappings as a batch.
    122      *
    123      * @param index Index to begin at
    124      * @param size Number of mappings to remove
    125      */
    126     public void removeAtRange(int index, int size) {
    127         final int end = Math.min(mSize, index + size);
    128         for (int i = index; i < end; i++) {
    129             removeAt(i);
    130         }
    131     }
    132 
    133     private void gc() {
    134         // Log.e("SparseArray", "gc start with " + mSize);
    135 
    136         int n = mSize;
    137         int o = 0;
    138         int[] keys = mKeys;
    139         Object[] values = mValues;
    140 
    141         for (int i = 0; i < n; i++) {
    142             Object val = values[i];
    143 
    144             if (val != DELETED) {
    145                 if (i != o) {
    146                     keys[o] = keys[i];
    147                     values[o] = val;
    148                     values[i] = null;
    149                 }
    150 
    151                 o++;
    152             }
    153         }
    154 
    155         mGarbage = false;
    156         mSize = o;
    157 
    158         // Log.e("SparseArray", "gc end with " + mSize);
    159     }
    160 
    161     /**
    162      * Adds a mapping from the specified key to the specified value,
    163      * replacing the previous mapping from the specified key if there
    164      * was one.
    165      */
    166     public void put(int key, E value) {
    167         int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
    168 
    169         if (i >= 0) {
    170             mValues[i] = value;
    171         } else {
    172             i = ~i;
    173 
    174             if (i < mSize && mValues[i] == DELETED) {
    175                 mKeys[i] = key;
    176                 mValues[i] = value;
    177                 return;
    178             }
    179 
    180             if (mGarbage && mSize >= mKeys.length) {
    181                 gc();
    182 
    183                 // Search again because indices may have changed.
    184                 i = ~ContainerHelpers.binarySearch(mKeys, mSize, key);
    185             }
    186 
    187             mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key);
    188             mValues = GrowingArrayUtils.insert(mValues, mSize, i, value);
    189             mSize++;
    190         }
    191     }
    192 
    193     /**
    194      * Returns the number of key-value mappings that this SparseArray
    195      * currently stores.
    196      */
    197     public int size() {
    198         if (mGarbage) {
    199             gc();
    200         }
    201 
    202         return mSize;
    203     }
    204 
    205     /**
    206      * Given an index in the range <code>0...size()-1</code>, returns
    207      * the key from the <code>index</code>th key-value mapping that this
    208      * SparseArray stores.
    209      *
    210      * <p>The keys corresponding to indices in ascending order are guaranteed to
    211      * be in ascending order, e.g., <code>keyAt(0)</code> will return the
    212      * smallest key and <code>keyAt(size()-1)</code> will return the largest
    213      * key.</p>
    214      */
    215     public int keyAt(int index) {
    216         if (mGarbage) {
    217             gc();
    218         }
    219 
    220         return mKeys[index];
    221     }
    222 
    223     /**
    224      * Given an index in the range <code>0...size()-1</code>, returns
    225      * the value from the <code>index</code>th key-value mapping that this
    226      * SparseArray stores.
    227      *
    228      * <p>The values corresponding to indices in ascending order are guaranteed
    229      * to be associated with keys in ascending order, e.g.,
    230      * <code>valueAt(0)</code> will return the value associated with the
    231      * smallest key and <code>valueAt(size()-1)</code> will return the value
    232      * associated with the largest key.</p>
    233      */
    234     @SuppressWarnings("unchecked")
    235     public E valueAt(int index) {
    236         if (mGarbage) {
    237             gc();
    238         }
    239 
    240         return (E) mValues[index];
    241     }
    242 
    243     /**
    244      * Given an index in the range <code>0...size()-1</code>, sets a new
    245      * value for the <code>index</code>th key-value mapping that this
    246      * SparseArray stores.
    247      */
    248     public void setValueAt(int index, E value) {
    249         if (mGarbage) {
    250             gc();
    251         }
    252 
    253         mValues[index] = value;
    254     }
    255 
    256     /**
    257      * Returns the index for which {@link #keyAt} would return the
    258      * specified key, or a negative number if the specified
    259      * key is not mapped.
    260      */
    261     public int indexOfKey(int key) {
    262         if (mGarbage) {
    263             gc();
    264         }
    265 
    266         return ContainerHelpers.binarySearch(mKeys, mSize, key);
    267     }
    268 
    269     /**
    270      * Returns an index for which {@link #valueAt} would return the
    271      * specified key, or a negative number if no keys map to the
    272      * specified value.
    273      * <p>Beware that this is a linear search, unlike lookups by key,
    274      * and that multiple keys can map to the same value and this will
    275      * find only one of them.
    276      * <p>Note also that unlike most collections' {@code indexOf} methods,
    277      * this method compares values using {@code ==} rather than {@code equals}.
    278      */
    279     public int indexOfValue(E value) {
    280         if (mGarbage) {
    281             gc();
    282         }
    283 
    284         for (int i = 0; i < mSize; i++)
    285             if (mValues[i] == value)
    286                 return i;
    287 
    288         return -1;
    289     }
    290 
    291     /**
    292      * Removes all key-value mappings from this SparseArray.
    293      */
    294     public void clear() {
    295         int n = mSize;
    296         Object[] values = mValues;
    297 
    298         for (int i = 0; i < n; i++) {
    299             values[i] = null;
    300         }
    301 
    302         mSize = 0;
    303         mGarbage = false;
    304     }
    305 
    306     /**
    307      * Puts a key/value pair into the array, optimizing for the case where
    308      * the key is greater than all existing keys in the array.
    309      */
    310     public void append(int key, E value) {
    311         if (mSize != 0 && key <= mKeys[mSize - 1]) {
    312             put(key, value);
    313             return;
    314         }
    315 
    316         if (mGarbage && mSize >= mKeys.length) {
    317             gc();
    318         }
    319 
    320         mKeys = GrowingArrayUtils.append(mKeys, mSize, key);
    321         mValues = GrowingArrayUtils.append(mValues, mSize, value);
    322         mSize++;
    323     }
    324 
    325     /**
    326      * {@inheritDoc}
    327      *
    328      * <p>This implementation composes a string by iterating over its mappings. If
    329      * this map contains itself as a value, the string "(this Map)"
    330      * will appear in its place.
    331      */
    332     @Override
    333     public String toString() {
    334         if (size() <= 0) {
    335             return "{}";
    336         }
    337 
    338         StringBuilder buffer = new StringBuilder(mSize * 28);
    339         buffer.append('{');
    340         for (int i=0; i<mSize; i++) {
    341             if (i > 0) {
    342                 buffer.append(", ");
    343             }
    344             int key = keyAt(i);
    345             buffer.append(key);
    346             buffer.append('=');
    347             Object value = valueAt(i);
    348             if (value != this) {
    349                 buffer.append(value);
    350             } else {
    351                 buffer.append("(this Map)");
    352             }
    353         }
    354         buffer.append('}');
    355         return buffer.toString();
    356     }
    357 }

    ##  ArrayMap

    * 与 SparseArray 类似

  • 相关阅读:
    java中的socket编程有关printStream的println方法和write方法
    json在php中的用法
    js的数组处理函数splice
    将博客搬至CSDN
    mapreduce导出MSSQL的数据到HDFS
    基于信息熵的无字典分词算法
    搜索引擎手记(三)之网页的去重
    算法之常用的距离和相似度度量
    搜索引擎手记(二)之爬虫的开发
    搜索引擎手记(一)之引擎工作的开始
  • 原文地址:https://www.cnblogs.com/liyiran/p/6519761.html
Copyright © 2020-2023  润新知