Sparse array系列

1危虱、特點:

時間換空間, 操作容器花費更多時間, 但是會減少內(nèi)存;

這篇博客重點分析:

1. SparseArray;
2. SparseIntArray;
3. ArrayMap;

2鸳吸、以SparseIntArray為例:

1溪猿、構(gòu)造函數(shù):
private int[] mKeys;
    private int[] mValues;
    private int mSize;
    public SparseIntArray() {
        this(10);
    }
public SparseIntArray(int initialCapacity) {
    if (initialCapacity == 0) {
        mKeys = EmptyArray.INT;
        mValues = EmptyArray.INT;
    } else {
        mKeys = ArrayUtils.newUnpaddedIntArray(initialCapacity);
        mValues = new int[mKeys.length];
    }
    mSize = 0;
}
libcore/luni/src/main/java/libcore/util/EmptyArray.java--->
public final class EmptyArray {
    private EmptyArray() {}

    public static final boolean[] BOOLEAN = new boolean[0];
    public static final byte[] BYTE = new byte[0];
    public static final char[] CHAR = new char[0];
    public static final double[] DOUBLE = new double[0];
    public static final float[] FLOAT = new float[0];
    public static final int[] INT = new int[0];
    public static final long[] LONG = new long[0];

    public static final Class<?>[] CLASS = new Class[0];
    public static final Object[] OBJECT = new Object[0];
    public static final String[] STRING = new String[0];
    public static final Throwable[] THROWABLE = new Throwable[0];
}

上面代碼主要做了一件事:

  • 1妖滔、創(chuàng)建兩個數(shù)組, 分別存儲key和value;
2穴吹、put():
class SparseIntArray--->
public void put(int key, int value) {
    int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
    if (i >= 0) {
        mValues[i] = value;
    } else {
        i = ~i;
        mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key);
        mValues = GrowingArrayUtils.insert(mValues, mSize, i, value);
        mSize++;
    }
}

class ContainerHelpers--->
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;  
        }
    }
    return ~lo;  
}

class GrowingArrayUtils --->
public static int[] insert(int[] array, int currentSize, int index, int element) {
    assert currentSize <= array.length;
    if (currentSize + 1 <= array.length) {
        System.arraycopy(array, index, array, index + 1, currentSize - index);
        array[index] = element;
        return array;
    }
    int[] newArray = new int[growSize(currentSize)];
    System.arraycopy(array, 0, newArray, 0, index);
    newArray[index] = element;
    System.arraycopy(array, index, newArray, index + 1, array.length - index);
    return newArray;
}
public static int growSize(int currentSize) {
    return currentSize <= 4 ? 8 : currentSize * 2;
}

put主要做了下面幾件事:

  • 1盆昙、插入操作先通過二分查找, 找出key. 二分查找時間復(fù)雜度為O(logN); 而HashMap內(nèi)部維護的是一個數(shù)組, 查找時間復(fù)雜度為O(1); 所以就插入操作來說, HashMap會更快一些;
  • 2羽历、這個二分查找進行的挺巧妙的, 插入失敗返回~lo; 對返回值再繼續(xù)進行取反操作;
  • 3、然后依次將key和value插入到數(shù)組中去, 我們看看他的插入操作;
  • 4淡喜、假設(shè)我們插入操作一直是亂序的, 并且很頻繁, 會出現(xiàn)什么問題? 二分查找頻繁執(zhí)行. 每次都是O(logN), 如果數(shù)據(jù)量過大, 與HashMap O(1)比起來時間差距就會越來越明顯;
  • 5秕磷、System.arraycopy(array, index, array, index + 1, currentSize - index)與array[index] = element;這兩步操作就是將我們要插入的元素插入到指定位置. 畫個圖
調(diào)用arraycopy以后.png
2、get():
public int get(int key, int valueIfKeyNotFound) {
      int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
      if (i < 0) {
          return valueIfKeyNotFound;
      } else {
          return mValues[i];
      }
}

**查找就很簡單了, 因為在put方法執(zhí)行時的一系列操作可以保證數(shù)組是有序的, 所以查找的時間復(fù)雜度也是O(logN). ** 所以如果涉及到大數(shù)據(jù)量或者查找特別頻繁的操作, SparseArray系列并不適用;

3炼团、delete():
public void delete(int key) {
    int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
    if (i >= 0) {
        removeAt(i);
    }
}
public void removeAt(int index) {
    System.arraycopy(mKeys, index + 1, mKeys, index, mSize - (index + 1));
    System.arraycopy(mValues, index + 1, mValues, index, mSize - (index + 1));
    mSize--;
}

刪除操作也是挺簡單的, 時間復(fù)雜度也是為O(logN). 因為他進行的數(shù)組元素的整體拷貝. 與get方法一樣, 當刪除操作特別頻繁或者數(shù)據(jù)量很大時, 也是沒必要使用的;

綜上所述:
當涉及到數(shù)據(jù)量不是特別大時, 官方給出的建議是千以下, 并且操作不是特別頻繁時, 使用SparseArray系列. 因為它可以節(jié)省內(nèi)存空間, APP與Windows不一樣, 虛擬機為每個APP分配的內(nèi)存空間很有限, SparseArray主要從以下幾個方面節(jié)省內(nèi)存空間:

  • 1澎嚣、沒有自動裝箱的操作;
  • 2疏尿、沒有Entry對象;及其Hash映射關(guān)系;

3、ArrayMap:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末易桃,一起剝皮案震驚了整個濱河市褥琐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌晤郑,老刑警劉巖敌呈,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異造寝,居然都是意外死亡磕洪,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進店門匹舞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來褐鸥,“玉大人,你說我怎么就攤上這事赐稽〗虚牛” “怎么了?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵姊舵,是天一觀的道長晰绎。 經(jīng)常有香客問我,道長括丁,這世上最難降的妖魔是什么荞下? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮史飞,結(jié)果婚禮上尖昏,老公的妹妹穿的比我還像新娘。我一直安慰自己构资,他們只是感情好抽诉,可當我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著吐绵,像睡著了一般迹淌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上己单,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天唉窃,我揣著相機與錄音,去河邊找鬼纹笼。 笑死纹份,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的廷痘。 我是一名探鬼主播蔓涧,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼削咆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蠢笋?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤鳞陨,失蹤者是張志新(化名)和其女友劉穎昨寞,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體厦滤,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡援岩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了掏导。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片享怀。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖趟咆,靈堂內(nèi)的尸體忽然破棺而出添瓷,到底是詐尸還是另有隱情,我是刑警寧澤值纱,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布鳞贷,位于F島的核電站,受9級特大地震影響虐唠,放射性物質(zhì)發(fā)生泄漏搀愧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一疆偿、第九天 我趴在偏房一處隱蔽的房頂上張望咱筛。 院中可真熱鬧,春花似錦杆故、人聲如沸迅箩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽沙热。三九已至,卻和暖如春罢缸,著一層夾襖步出監(jiān)牢的瞬間篙贸,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工枫疆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留爵川,地道東北人。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓息楔,卻偏偏與公主長得像寝贡,于是被迫代替她去往敵國和親扒披。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,969評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Java8張圖 11圃泡、字符串不變性 12碟案、equals()方法、hashCode()方法的區(qū)別 13颇蜡、...
    Miley_MOJIE閱讀 3,707評論 0 11
  • Android開發(fā)者都知道Lint在我們使用HashMap的時候會給出警告——使用SparseArray會優(yōu)化內(nèi)存...
    扈扈哈嘿閱讀 17,766評論 2 21
  • 都知道這么一句話价说,沒什么也不能沒錢,有什么也不能有病风秤。 沒錢的日子鳖目,真的很苦; 有病的日子缤弦,真的很難受领迈。 如果,生...
    煩人的昵稱閱讀 162評論 0 0
  • 阿凡提真棒
    阿提蘭閱讀 216評論 0 0
  • c語言中包含char碍沐、int狸捅、float、double等基本數(shù)據(jù)類型累提,本節(jié)主要研究一下這些基本數(shù)據(jù)類型的特點及存儲...
    labi3285閱讀 157評論 0 0