Android Sparsearray Source Analysis

Source: Internet
Author: User

Preface last night to add an int to the dictionary table in the Android application, using HashMap implementation, Eclipse gave a warning, last night, the project on-line tension, I directly ignored, today I looked at the specific eclipse hints as follows:
Use new sparsearray<string> (...) instead for better performance
This warning is meant to be replaced with Sparsearray to get better performance.
SOURCE because Sparsearray overall code is relatively simple, first show the source code, and then analyze why use sparsearray than using HashMap have better performance.
public class Sparsearray<e> implements cloneable {private static final object DELETED = new Object ();    Private Boolean mgarbage = false;    Private int[] Mkeys;    Private object[] mvalues;    private int msize;     /** * Creates a new sparsearray containing no mappings.    */Public Sparsearray () {this (10); }/** * Creates a new sparsearray containing no mappings that won't * require any additional memory Allocati  On to store the specified * number of mappings.     If you supply an initial capacity of 0, the * sparse array would be initialized with a light-weight representation     * Not requiring any additional array allocations. */public Sparsearray (int initialcapacity) {if (initialcapacity = = 0) {Mkeys = Containerhelpers.emp            ty_ints;        Mvalues = containerhelpers.empty_objects;            } else {initialcapacity = Arrayutils.idealintarraysize (initialcapacity); Mkeys = new Int[initiaLcapacity];        Mvalues = new Object[initialcapacity];    } msize = 0; } @Override @SuppressWarnings ("unchecked") public sparsearray<e> Clone () {sparsearray<e> Clon        e = null;            try {clone = (sparsearray<e>) super.clone ();            Clone.mkeys = Mkeys.clone ();        Clone.mvalues = Mvalues.clone ();    } catch (Clonenotsupportedexception cnse) {/* ignore */} return clone; }/** * Gets the Object mapped from the specified key, or <code>null</code> * If no such mapping ha     s been made.    */Public E get (int key) {return get (key, NULL); }/** * Gets the object mapped from the specified key, or the specified object * If no such mapping have been MA     De. */@SuppressWarnings ("unchecked") public E get (int key, E valueifkeynotfound) {int i = Containerhelpers.bina        Rysearch (Mkeys, msize, key); if (I < 0 | | | mvalues[I] = = DELETED) {return valueifkeynotfound;        } else {return (E) mvalues[i];     }}/** * Removes the mapping from the specified key, if there is any.        */public void Delete (int key) {int i = Containerhelpers.binarysearch (Mkeys, msize, key);                if (I >= 0) {if (mvalues[i]! = DELETED) {Mvalues[i] = DELETED;            Mgarbage = true;     }}}/** * Alias for {@link #delete (int)}.    */public void remove (int key) {delete (key);     }/** * Removes the mapping at the specified index.            */public void removeAt (int index) {if (Mvalues[index]! = DELETED) {Mvalues[index] = DELETED;        Mgarbage = true;     }}/** * Remove a range of mappings as a batch. * * @param index index to begin at * @param size number of mappings to remove */public void Removeatrange ( int index, int size) {finAl int end = Math.min (msize, index + size);        for (int i = index; i < end; i++) {removeAt (i);        }} private void GC () {//LOG.E ("Sparsearray", "GC start with" + msize);        int n = msize;        int o = 0;        Int[] keys = Mkeys;        Object[] values = mvalues;            for (int i = 0; i < n; i++) {Object val = values[i];                    if (val! = DELETED) {if (i! = O) {Keys[o] = keys[i];                    Values[o] = val;                Values[i] = null;            } o++;        }} Mgarbage = false;        Msize = O;    LOG.E ("Sparsearray", "GC End with" + msize);  }/** * Adds a mapping from the specified key to the specified value, * Replacing the previous mapping from the     Specified key if there * was one.        */public void put (int key, E value) {int i = Containerhelpers.binarysearch (Mkeys, msize, key); If (I >= 0)        {Mvalues[i] = value;            } else {i = ~i;                if (i < msize && mvalues[i] = = DELETED) {mkeys[i] = key;                Mvalues[i] = value;            Return                } if (Mgarbage && msize >= mkeys.length) {GC ();                Search again because indices may have changed.            i = ~containerhelpers.binarysearch (Mkeys, msize, key);                } if (Msize >= mkeys.length) {int n = arrayutils.idealintarraysize (msize + 1);                int[] Nkeys = new Int[n];                object[] nvalues = new Object[n];                LOG.E ("Sparsearray", "grow" + mkeys.length + "to" + N);                System.arraycopy (Mkeys, 0, Nkeys, 0, mkeys.length);                System.arraycopy (mvalues, 0, nvalues, 0, mvalues.length);                Mkeys = Nkeys;            Mvalues = nvalues; } if (Msize-i! = 0) {//LOG.E ("Sparsearray", "move" + (msize-i));                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++;     }}/** * Returns the number of key-value mappings that this sparsearray * currently stores.        */public int size () {if (mgarbage) {GC ();    } return msize; }/** * Given an index of the range <code>0...size () -1</code>, returns * The key from the <code&     gt;index</code>th Key-value mapping that this * Sparsearray stores.  * * <p>the keys corresponding to indices in ascending order is guaranteed to * is in ascending order, e.g., <code>keyat (0) </code> would return the * smallest key and <code>keyat (size ()-1) </code> would re Turn the largest * key.</p>    */public int Keyat (int index) {if (mgarbage) {GC ();    } return Mkeys[index]; }/** * Given an index of the range <code>0...size () -1</code>, returns * The value from the <cod     e>index</code>th Key-value mapping that this * Sparsearray stores.  * * <p>the values corresponding to indices in ascending order is guaranteed * to is associated with keys in  Ascending order, e.g, * <code>valueat (0) </code> would return the value associated with the * smallest      Key and <code>valueat (size ()-1) </code> would return the value * associated with the largest key.</p>        */@SuppressWarnings ("unchecked") public E valueat (int index) {if (mgarbage) {GC ();    } return (E) Mvalues[index]; }/** * Given an index in the range <code>0...size () -1</code>, sets a new * value for the <code& gt;index</code>th KEy-value mapping that this * Sparsearray stores.        */public void setvalueat (int index, E value) {if (mgarbage) {GC ();    } Mvalues[index] = value; }/** * Returns the index for which {@link #keyAt} would return the * specified key, or a negative number if th     E specified * key is not mapped.        */public int indexofkey (int key) {if (mgarbage) {GC ();    } return Containerhelpers.binarysearch (Mkeys, msize, key); }/** * Returns an index for which {@link #valueAt} would return the * specified key, or a negative number if n     o keys map to the * specified value. * <p>beware that's a linear search, unlike lookups by key, * and that multiple keys can map to the same VA     Lue and this would * find only one of them.  * <p>note also that unlike most collections ' {@code indexOf} methods, * This method compares values using {@code = =} rather than {@code equals}. */public int indexofvalue (E value) {if (mgarbage) {GC ();        } for (int i = 0; i < msize; i++) if (mvalues[i] = = value) return i;    return-1;     }/** * Removes all key-value mappings from this sparsearray.        */public void Clear () {int n = msize;        Object[] values = mvalues;        for (int i = 0; i < n; i++) {values[i] = null;        } msize = 0;    Mgarbage = false; }/** * Puts a Key/value pair into the array, optimizing for the case where * the key was greater than all exist     ing keys in the array. */public void append (int key, E value) {if (msize! = 0 && key <= mkeys[msize-1]) {put            (key, value);        Return        } if (Mgarbage && msize >= mkeys.length) {GC ();        } int pos = msize; if (pos >= mkeys.length) {int n = arrayutils.idealintArraySize (pos + 1);            int[] Nkeys = new Int[n];            object[] nvalues = new Object[n];            LOG.E ("Sparsearray", "grow" + mkeys.length + "to" + N);            System.arraycopy (Mkeys, 0, Nkeys, 0, mkeys.length);            System.arraycopy (mvalues, 0, nvalues, 0, mvalues.length);            Mkeys = Nkeys;        Mvalues = nvalues;        } Mkeys[pos] = key;        Mvalues[pos] = value;    Msize = pos + 1; }/** * {@inheritDoc} * * <p>this implementation composes a string by iterating + its mappings.     If * This maps contains itself as a value, the string "(This map)" * would appear in its place.        */@Override public String toString () {if (size () <= 0) {return ' {} ';        } StringBuilder buffer = new StringBuilder (msize * 28);        Buffer.append (' {');            for (int i=0; i<msize; i++) {if (i > 0) {buffer.append (",");          }  int key = Keyat (i);            Buffer.append (key);            Buffer.append (' = ');            Object value = valueat (i);            if (value! = this) {buffer.append (value);            } else {buffer.append ("(This Map)");        }} buffer.append ('} ');    return buffer.tostring (); }}

First, take a look at the Sparsearray constructor:
/** * Creates A     New Sparsearray containing no mappings.    */Public Sparsearray () {this (10); }/** * Creates a new sparsearray containing no mappings that won't * require any additional memory Allocati  On to store the specified * number of mappings.     If you supply an initial capacity of 0, the * sparse array would be initialized with a light-weight representation     * Not requiring any additional array allocations. */public Sparsearray (int initialcapacity) {if (initialcapacity = = 0) {Mkeys = Containerhelpers.emp            ty_ints;        Mvalues = containerhelpers.empty_objects;            } else {initialcapacity = Arrayutils.idealintarraysize (initialcapacity);            Mkeys = new Int[initialcapacity];        Mvalues = new Object[initialcapacity];    } msize = 0; }
As you can see from the construction method, the size of the container is also pre-set, with a default size of 10.
Let's take a look at adding data operations:
    /** * Adds A mapping from the specified key to the specified value, * Replacing the previous mapping from the     Specified key if there * was one.        */public void put (int key, E value) {int i = Containerhelpers.binarysearch (Mkeys, msize, key);        if (I >= 0) {Mvalues[i] = value;            } else {i = ~i;                if (i < msize && mvalues[i] = = DELETED) {mkeys[i] = key;                Mvalues[i] = value;            Return                } if (Mgarbage && msize >= mkeys.length) {GC ();                Search again because indices may have changed.            i = ~containerhelpers.binarysearch (Mkeys, msize, key);                } if (Msize >= mkeys.length) {int n = arrayutils.idealintarraysize (msize + 1);                int[] Nkeys = new Int[n];                object[] nvalues = new Object[n]; LOG.E ("Sparsearray", "grow "+ Mkeys.length +" to "+ N);                System.arraycopy (Mkeys, 0, Nkeys, 0, mkeys.length);                System.arraycopy (mvalues, 0, nvalues, 0, mvalues.length);                Mkeys = Nkeys;            Mvalues = nvalues;                } if (Msize-i! = 0) {//LOG.E ("Sparsearray", "move" + (msize-i));                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++; }    }

Look at the data again:
    /**     * Gets the Object mapped from the specified key, or <code>null</code>     * If no such mapping have bee N made.     */Public    E get (int key) {        return get (key, NULL);    }    /**     * Gets The object mapped from the specified key, or the specified object     * If no such mapping have been made.
   */    @SuppressWarnings ("unchecked") 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];        }    }

As you can see, in the process of put data and get data, a binary lookup algorithm is called uniformly, which is the core of sparsearray to improve efficiency.
    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    }
Personally, the method of (lo + hi) >>> 1 is somewhat odd, and it is better to use Lo + (Hi-lo)/2 directly.




Android Sparsearray Source Analysis

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.