Android arraymap Source Code Analysis _android

Source: Internet
Author: User
Tags int size

Analysis of the source before the introduction of the ARRAYMAP storage structure, ARRAYMAP data storage is different from HashMap and Sparsearray.

Java provides hashmap, but HashMap is too much space for mobile phones, so Android offers Sparsearray and Arraymap. Both are based on two-point lookup, so when the data volume is large, the worst efficiency is much slower than HashMap. Therefore, the proposed quantity is more suitable in thousand or less.

First, Sparsearray

The Sparsearray corresponding key can only be int type, it does not boxing the key. It uses two arrays, one saving key, and one saving value.

Sparsearray uses a binary lookup to find the insertion position for the key. So make sure Mkeys arrays are ordered.

Remove will not immediately clean the deleted data, but the data on one is marked as delete (an object). Call GC cleanup in the necessary steps to delete space.

Second, Arraymap

Focus on the introduction of Arraymap.

Start with a four array of Arraymap. Mhashes, which is used to hold the key corresponding to the Hashcode;marray, which holds the value pair (Key,value), which is structured as [Key1,value1,key2,value2,key3,value3,......] ; Mbasecache, cache, if the amount of ARRAYMAP data from 4 to 8, use the array to save the mhashes and Marray used before, so if the amount of data back to 4, you can use the previous array again, do not need to request space again, this saves a certain amount of time Mtwicebasecache, corresponding to Mbasecache, but the trigger condition is that the amount of data increases from 8 to 12.

The amount of data mentioned above increases to 12, why not 16? This is also considered an optimized point for arraymap, which does not grow 1 time times each time, but instead uses the following method (Msize+ (msize>>1)), that is, an increase of 1/2 each time.

With the above instructions, it is much easier to read the code.

1, a lot of places to use the IndexOf

This uses a two-point lookup to find the corresponding index

int indexOf (Object key, int hash) {Final int N = msize;
    Important fast case:if "Nothing" in the.
    The array is empty, returning directly if (N = = 0) {return ~0;

    }///Two point lookup, not to elaborate int index = Containerhelpers.binarysearch (mhashes, N, hash);
    If The hash code wasn ' t found, then we have no entry for this key.
    No hashcode found, returned index, a negative number if (Index < 0) {return index;
    }//If the key at the returned index matches, that ' s what we want.
    Compares key values, the same returns index if (Key.equals (marray[index<<1])) {return index;
    //Search for a matching key after the index.
    If the corresponding key value of the returned index is unequal to the key value passed in, the key may correspond to the int end after index; for (end = index + 1; end < N && Mhashes[end] = = Hash; end++) {if (Key.equals (marray[end << 1))) R
    Eturn end;
    //Search for a matching key before the index.
    After the sentence, there is no, that must be in front. for (int i = index-1 I >= 0 && mhashes[i] = = hash; i--) {if (Key.equals (marray[i << 1])) return i; }//Key not found--return negative value indicating where a//The new entry for this Key is should go. We use the ' End of the '//hash chain to reduce the number of array entries that'll//need to is copied when Inse
    Rting.
  Mao did not find, it must be no, returned a negative return ~end;

 }

2. Look at the Put method

Public V-Put (K key, V value) {final int hash;
    int index;
      Key is empty, the corresponding index is found by indexofnull, and if not NULL, find the corresponding index if (key = = null) {hash = 0 by indexof;
    index = Indexofnull ();
      else {hash = Key.hashcode ();
    index = indexOf (key, hash); //index is greater than or equal to 0, must have been put before the same key, directly replace the corresponding value.
    Because the Marray not only saved value, but also saved the key.
    Its structure is [Key1,value1,key2,value2,key3,value3,......]
      Therefore, it is necessary to add the index multiplication 2 to Key,index multiply 2 plus 1 corresponding to the value if (index >= 0) {index = (index<<1) + 1;
      Final V old = (v) marray[index];
      Marray[index] = value;
    return old;
    //Take positive number index = ~index; The size of the msize, that is, the amount of data that has been saved is the same as the length of the mhashes, you need to enlarge the IF (msize >= mhashes.length) {//capacity after the size, there are several stalls, base_size (4), Base_si Ze twice times (8), msize+ (msize>>1) (larger than the previous volume of data expansion 1/2) Final int n = msize >= (base_size*2)? (Msize+ (Msize>>1)): (Msize >= base_size?

      (base_size*2): base_size); if (DEBUG) log.d (TAG, "Put:grow from" + Mhashes.length + "to" + N);
      Final int[] ohashes = mhashes;
      Final object[] Oarray = Marray;

      The realization allocarrays (n) of the expansion method;
        After the expansion, the original data needs to be copied to the new array if (Mhashes.length > 0) {if (DEBUG) log.d (TAG, "Put:copy 0-" + msize + "to 0");
        System.arraycopy (ohashes, 0, mhashes, 0, ohashes.length);
      System.arraycopy (Oarray, 0, Marray, 0, oarray.length);
      //See if the discarded array is still in use value//if the data amount of the discarded array is 4 or 8, the value may be used and can be used directly later. If the amount of data discarded is too large, throw it out, or take up too much memory.
      If a waste of memory, but also a lot of effort, add a class to do what.
    Freearrays (Ohashes, Oarray, msize); The hashcode sort for the put key is not ranked at the end (index does not indicate the end of the array), so the data after index must be moved if (Index < msize) {if (DEBUG) LOG.D (
      TAG, "Put:move" + Index + "-" + (Msize-index) + "to" + (index+1));
      System.arraycopy (mhashes, index, mhashes, index + 1, msize-index);
    System.arraycopy (Marray, index << 1, Marray, (index + 1) << 1, (Msize-index) << 1); //Save the data in an array. See it., key and value are in Marray; Hashcode to mhashes mhashes[index] = hash;
    MARRAY[INDEX&LT;&LT;1] = key;
    marray[(index<<1) +1] = value;
    msize++;
  return null;

 }

   3. Remove method

The Remove method, under certain conditions, will redistribute memory to ensure that the memory allocated to Arraymap is in a reasonable range, reducing memory footprint. But as you can see from here, Android uses time to change space. The frequent allocation of reclaimed memory from any angle can be time-consuming.

The remove ultimately uses the RemoveAt method, which only explains the RemoveAt

 /** * Remove The Key/value mapping at the given index.
   * @param index The desired index, must be between 0 and {@link #size ()}-1.
   * @return Returns The value that is stored at this index.
    * * Public V removeat (int index) {final Object old = marray[(index << 1) + 1];
    If the amount of data is less than or equal to 1, after deleting the element, no array is empty and two arrays are emptied.
      if (msize <= 1) {//Now empty.
      if (DEBUG) log.d (TAG, "remove:shrink from" + mhashes.length + "to 0");
      Put has been described freearrays (mhashes, Marray, msize);
      Mhashes = Emptyarray.int;
      Marray = Emptyarray.object;
    msize = 0; else {//If the original requested array holds more data than twice times (8) of base_size, and the amount of data currently stored is only 1/3 of the number of requests,//You will need to reallocate space and have reduced memory occupancy if (MHASHES.L Ength > (base_size*2) && Msize < MHASHES.LENGTH/3) {//shrunk enough to reduce SIZE of arrays. 
        We don ' t allow it to//shrink smaller than (base_size*2) to avoid flapping//that and between. The size of the new array finalint n = msize > (base_size*2)?

        (Msize + (msize>>1)): (base_size*2);

        if (DEBUG) log.d (TAG, "remove:shrink from" + Mhashes.length + "to" + N);
        Final int[] ohashes = mhashes;
        Final object[] Oarray = Marray;

        Allocarrays (n);
        msize--; 
          The data before index is copied to the new array if (Index > 0) {if (DEBUG) log.d (TAG, "remove:copy from 0-" + index + "to 0");
          System.arraycopy (ohashes, 0, mhashes, 0, index);
        System.arraycopy (Oarray, 0, Marray, 0, index << 1); //Copy the data after the index to the new array, and (index>0) to the branch, the index position of the data deleted the IF (Index < msize) {if (DEBUG) Log
          . D (TAG, "remove:copy from" + (index+1) + "-" + Msize + "to" + index);
          System.arraycopy (ohashes, index + 1, mhashes, index, msize-index);
        System.arraycopy (Oarray, (index + 1) << 1, Marray, index << 1, (Msize-index) << 1);
     }} else {   msize--; 
              Move the data after the index forward if (Index < msize) {if (DEBUG) log.d (TAG, "Remove:move" + (index+1) + "-" + msize
          + "to" + index);
          System.arraycopy (mhashes, index + 1, mhashes, index, msize-index);
        System.arraycopy (Marray, (index + 1) << 1, Marray, index << 1, (Msize-index) << 1);
        }//shifted last data empty marray[msize << 1] = null;
      marray[(msize << 1) + 1] = null;
  } return (V) old;

 }

  4, Freearrays

Put in a note, here is not an overview, directly on the code, to verify the above statement.

  private static void Freearrays (final int[] hashes, final object[] array, final int size) {//The number of obsolete arrays is twice times that of Base_size
      (8), the discarded array is saved with mtwicebasecache;//If the number is base_size (4), the discarded array is saved with mbasecache (hashes.length = = (base_size*2)) { Synchronized (Arraymap.class) {if (Mtwicebasecachesize < cache_size) {//array is a newly discarded array, MTWICEBASECAC
          He if the content, then put into array[0] position,//In the allocarrays will be removed from array[0], put back mtwicebasecache array[0] = Mtwicebasecache; ARRAY[1] holds a hash array.
          Because each element in the array is an object, each element can hold an array array[1] = hashes;
          Clears the data for index 2 and after for (int i= (size<<1)-1; i>=2; i--) {array[i] = null;
          } Mtwicebasecache = array;
          mtwicebasecachesize++;
        if (DEBUG) log.d (TAG, "storing 2x cache" + array + "now have" + Mtwicebasecachesize + "entries");
  }} else if (Hashes.length = base_size) {synchronized (Arraymap.class) {      if (Mbasecachesize < cache_size) {//code comments can be referenced above, do not repeat the description of the array[0] = Mbasecache;
          ARRAY[1] = hashes;
          for (int i= (size<<1)-1; i>=2; i--) {array[i] = null;
          } Mbasecache = array;
          mbasecachesize++;
        if (DEBUG) log.d (TAG, "storing 1x Cache" + Array + "now have" + Mbasecachesize + "entries");
 }
      }
    }
  }

5, Allocarrays

Forget it, feel nothing to say, see understand freearrays,allocarrays naturally understand.

In general, the number of new arrays produces 3 branches, the number is base_size (4), the discarded array from the Mbasecache, twice times (8) of base_size, and the discarded array from Mtwicebasecache; Previously discarded arrays are not stored because memory is too expensive, in which case reallocation of memory.

 6. Clear and Erase

Clear clears the array, and if you add elements to the array again, you need to reapply for space; erase clears the array in the array, and the space is still there.

7, get

The main logic is in the indexof, the rest of the code does not need to analyze, read all speak (chuckle).

Thank you for reading, I hope to help you, thank you for your support for this site!

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.