Android開發中高效的數據結構用SparseArray代替HashMap

likeo 9年前發布 | 51K 次閱讀 Android開發 移動開發 SparseArray

android開發中,在java2ee或者android中常用的數據結構有Map,List,Set,但android作為移動平臺,有些api(很多都是效率問題)顯然不夠理想,本著造更好輪子的精神,android團隊編寫了自己的api用來代替java api

1、SimpleArrayMap<K,V>與ArrayMap<K,V>

實質上ArrayMap繼承自SimpleArrayMap,主要是為了實現像HashMap一樣的api方法,讓習慣使用HashMap的開發者感覺不到差異,本質上是SimpleArrayMap+Map的再封裝。

一般來說使用這2個類主要來代替HashMap,因為他們比HashMap更加高效,對內存也進行了優化。

2、SparseArray<T>與SparseArrayCompat<T>和LongSparseArray<T>

這3個類中,前2個基本上是同一類,只不過第二個類有removeAt方法,第三個是Long類型的。

這3個類也是用來代替HashMap,只不過他們的鍵(key)的類型是整型Integer或者Long類型,在實際開發中,如月份縮寫的映射,或者進行文件緩存映射,viewHolder都特別適用

3、AtomicFile

AtomicFile首先不是用來代替File的,而是作為File的輔助類從在, AtomicFile的作用是實現事務性原子操作,即文件讀寫必須完整,適合多線程中的文件讀寫操作。

用來實現多線程中的文件讀寫的安全操作

----
#####用SparseArray代替HashMap
SparseArray是android提供的一個工具類,它可以用來替代hashmap進行對象的存儲,其內部實現了一個矩陣壓縮算法,很適合存儲稀疏矩陣的。

PS:support包中還提供了兼容的類SparseArrayCompat,基本和SparseArray是同一個類,只不過第二個類有removeAt方法

針對源碼的詳細分析:[http://stormzhang.com/android/2013/08/01/android-use-sparsearray-for-performance-optimization/](http://stormzhang.com/android/2013/08/01/android-use-sparsearray-for-performance-optimization/ "http://stormzhang.com/android/2013/08/01/android-use-sparsearray-for-performance-optimization/")

一、和Hashmap的對比

既然android推薦用這個東西,自然有用它的道理。其內部實現了壓縮算法,可以進行矩陣壓縮,大大減少了存儲空間,節約內存。此外它的查找算法是二分法,提高了查找的效率。

替換原則:

1>

如果用到了: HashMap<Integer, E> hashMap = new HashMap<Integer, E>();

可以替換為:SparseArray<E> sparseArray = new SparseArray<E>();

2>

如果用到了:HashMap<Integer, Boolean> hashMap = new HashMap<Integer, Boolean>

可以替換為:SparseBooleanArray array = new SparseBooleanArray();

3>

如果用到了:HashMap<Integer, Integer> hashMap = new HashMap<Integer, Integer>

可以替換為:SparseIntArray array = new SparseIntArray();

二、用法

既然是鍵值對那么就有增刪改查,但要記得先初始化:


        Button btn = null; // 測試view,無意義
        Button btn02 = null; // 測試view,表示新增的對象
        final int KEY = 1;

        /*
         * SparseArray指的是稀疏數組(Sparse
         * array),所謂稀疏數組就是數組中大部分的內容值都未被使用(或都為零),在數組中僅有少部分的空間使用
         * 。因此造成內存空間的浪費,為了節省內存空間,并且不影響數組中原有的內容值,我們可以采用一種壓縮的方式來表示稀疏數組的內容。
         */
        SparseArray<View> array = new SparseArray<View>();


 

2.1 增加數據


/* 增加數據 */
        //public void put(int key, E value) {}
        array.put(KEY, btn);
        //public void append(int key, E value){}
        array.append(KEY, btn);


 

2.2 修改數據


  /* 修改數據 */
        //在put數據之前,會先查找要put的數據是否已經存在,如果存在就是修改,不存在就添加。
        //public void put(int key, E value)
        array.put(KEY, btn);
        //public void setValueAt(int index, E value)
        array.setValueAt(KEY, btn02);


 

2.3 查找數據


  /* 查找數據 */
        //public E get(int key)
        array.get(KEY);
        //public E get(int key, E valueIfKeyNotFound)
        //其中get(int key)也只是調用了 get(int key,E valueIfKeyNotFound),最后一個從傳參的變量名就能看出,傳入的是找不到的時候返回的值.get(int key)當找不到的時候,默認返回null。
        array.get(KEY, btn); // 如果這個key找不到value,那么就返回第二個參數。和default value一樣


 

2.4 通過位置,查找鍵的值


  // 查看第幾個位置的鍵:
        //public int keyAt(int index)
        array.keyAt(1); // 如果找不到就返回-1


 

2.5 通過位置,查找值


        // 查看第幾個位置的值:
        //public E valueAt(int index)
        array.valueAt(1);
        // 查看值所在位置,沒有的話返回-1:
        //public int indexOfValue(E value)
        array.indexOfValue(btn);



三、測試代碼

    package com.kale.pictest;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.util.Log;
    import android.util.SparseArray;
    import android.util.SparseBooleanArray;
    import android.view.View;
    import android.widget.Button;
    
    /**
     * @author:
     * @description  :
     * @web : http://stormzhang.com/android/2013/08/01/android-use-sparsearray-for-performance-optimization/
     * @date  :2015年1月19日
     */
    public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
        Log.d("TAG", "Max memory is " + maxMemory + "KB");
        
        
        Button btn = null; // 測試view,無意義
        Button btn02 = null; // 測試view,表示新增的對象
        final int KEY = 1;

        /*
         * SparseArray指的是稀疏數組(Sparse
         * array),所謂稀疏數組就是數組中大部分的內容值都未被使用(或都為零),在數組中僅有少部分的空間使用
         * 。因此造成內存空間的浪費,為了節省內存空間,并且不影響數組中原有的內容值,我們可以采用一種壓縮的方式來表示稀疏數組的內容。
         */
        SparseArray<View> array = new SparseArray<View>();
        
        /* 增加數據 */
        //public void put(int key, E value) {}
        array.put(KEY, btn);
        //public void append(int key, E value){}
        array.append(KEY, btn);
        
        /* 修改數據 */
        //在put數據之前,會先查找要put的數據是否已經存在,如果存在就是修改,不存在就添加。
        //public void put(int key, E value)
        array.put(KEY, btn);
        //public void setValueAt(int index, E value)
        array.setValueAt(KEY, btn02);
        
        /* 查找數據 */
        //public E get(int key)
        array.get(KEY);
        //public E get(int key, E valueIfKeyNotFound)
        //其中get(int key)也只是調用了 get(int key,E valueIfKeyNotFound),最后一個從傳參的變量名就能看出,傳入的是找不到的時候返回的值.get(int key)當找不到的時候,默認返回null。
        array.get(KEY, btn); // 如果這個key找不到value,那么就返回第二個參數。和default value一樣
        
        // 查看第幾個位置的鍵:
        //public int keyAt(int index)
        array.keyAt(1); // 如果找不到就返回-1
        
        // 查看第幾個位置的值:
        //public E valueAt(int index)
        array.valueAt(1);
        // 查看值所在位置,沒有的話返回-1:
        //public int indexOfValue(E value)
        array.indexOfValue(btn);
        
        SparseBooleanArray d;
    }
    }


測試代碼四:

    public class FragmentPagerItemAdapter extends FragmentPagerAdapter {

    private final FragmentPagerItems mPages;
    private final SparseArrayCompat<WeakReference<Fragment>> mHolder;

    public FragmentPagerItemAdapter(FragmentManager fm, FragmentPagerItems pages) {
        super(fm);
        mPages = pages;
        mHolder = new SparseArrayCompat<>(pages.size());
    }

    @Override
    public int getCount() {
        return mPages.size();
    }

    @Override
    public Fragment getItem(int position) {
        return getPagerItem(position).instantiate(mPages.getContext(), position);
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Object item = super.instantiateItem(container, position);
        if (item instanceof Fragment) {
            mHolder.put(position, new WeakReference<Fragment>((Fragment) item));
        }
        return item;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        mHolder.remove(position);
        super.destroyItem(container, position, object);
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return getPagerItem(position).getTitle();
    }

    @Override
    public float getPageWidth(int position) {
        return super.getPageWidth(position);
    }

    public Fragment getPage(int position) {
        final WeakReference<Fragment> weakRefItem = mHolder.get(position);
        return (weakRefItem != null) ? weakRefItem.get() : null;
    }

    protected FragmentPagerItem getPagerItem(int position) {
        return mPages.get(position);
    }

    }

 本文由用戶 likeo 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!