sparsearray指的是稀疏陣列,就是陣列中並沒有填滿,只有部分有值,這樣造成了記憶體浪費,往往採用的是壓縮的方式來儲存內容。
了解下sparsearray怎麼儲存的以及sparsearray的擴容。
看下**
public class sparsearrayimplements cloneable
public sparsearray(int initialcapacity) else
msize = 0;
}
看下put()方法
public void put(int key, e value) else
//如果要**並且存入的輸入大於等於當前key對映陣列的長度,就要gc,這個**後面看
if (mgarbage && msize >= mkeys.length)
mkeys = growingarrayutils.insert(mkeys, msize, i, key);
mvalues = growingarrayutils.insert(mvalues, msize, i, value);
msize++;
}}
看下這個二分查詢containerhelpers.binarysearch(),這個方法挺有意思的,在於即使沒有找到你想要的值,但是確是會返回給你乙個最佳位置。
//這裡要注意的是size並不是array的長度,
//而是你已經放入物件的數目,別忘了二分查詢是建立在有序陣列上的,
//你存進去的數其實已經排好序了,
//這也是為什麼size的大小不是array的長度,如果是整個陣列長度,
//那要查詢的就不是乙個有序陣列了,在size長度內的數是確定有序的
static int binarysearch(int array, int size, int value) else if (midval > value) else
}return ~lo; // value not present如果沒找到,會返回在當前陣列當中的最佳位置
}
測試一陣列 int arr = 為例,我們分別使用這個二分查詢方法查詢1,6,8,12,看看返回結果是什麼,binarysearch(arr,4,1) = -1;
查詢的值
返回的實際位置值 (位置取反後的值)
10(-1)
62(找到了直接返回位置)
83(-4)
124(-5)
為什麼要取反呢?是為了區分找到和沒找到,找到返回結果是正數,沒找到就是負數,看上面的表一目了然。
如果要存入乙個小於陣列中已經存入的數1,其返回的最佳位置就是0,表示要在0這個位置插入乙個新數,
查乙個大於陣列中已存入的數12,返回的最佳位置就是已存入的最後位置+1,而查詢乙個中間數8,也是其應該插入的位置,像插入1,8這兩個數其實是有問題的,因為要插入的位置上已經有值了,那sparsearray怎麼處理的呢?答案先給出來,就是從要插入的位置開始,陣列整體往後移。
再回去看為什麼put()方法裡面的i為什麼要區分正負就比較清楚了。來看下put()方法裡面的這段**
//如果要**並且存入的輸入大於等於當前key對映陣列的長度,
//就要gc,這個**後面看
if (mgarbage && msize >= mkeys.length)
gc**如下
private void gc() ,3與5之間的0表示刪除過的數,
//那麼這麼陣列重排序的話是不需要所有都重拍的,
//只要把刪除位置後面的數往前挪一下就行了,gc方法就是這個原理
int n = msize;
int o = 0;
int keys = mkeys;
object values = mvalues;
for (int i = 0; i < n; i++)
o++;}}
mgarbage = false;
msize = o;
// log.e("sparsearray", "gc end with " + msize);
}
gc這個方法其實也挺有意思的,兩個指標用來排序的方法,面試的時候經常會用到。
回到正題在看下sparsearray的put裡面還剩下什麼沒有解剖~
mkeys = growingarrayutils.insert(mkeys, msize, i, key);
mvalues = growingarrayutils.insert(mvalues, msize, i, value);
msize++;
也就growingarrayutils.insert這個方法了,看**
//大概說一下把,前面二分查詢幫我們找到了最佳位置,
//我們現在需要在這個最佳位置插入資料,
//前面說過就是把當前位置後面的資料正題後移再放入我們的資料就行了
public static int insert(int array, int currentsize, int index, int element) 從index=1開始複製,複製長度為5,複製後的結果就是了
array[index] = element;
return array;
}//這就是擴容了,新建了乙個陣列,長度*2
int newarray = new int[growsize(currentsize)];
//新舊陣列拷貝,先拷貝最佳位置之前的到新陣列
system.arraycopy(array, 0, newarray, 0, index);
newarray[index] = element;//直接在新陣列上賦值
//然後拷貝舊陣列最佳位置index起的所有數到新陣列裡面,
//只是做了分段拷貝而已
system.arraycopy(array, index, newarray, index + 1, array.length - index);
return newarray;
}
sparsearray的擴容機制大致上就這些,其實就最後這一小部分**。至於system.arraycopy()方法就不討論了,網上都有,就是比遍歷賦值效率要高些。 hashMap擴容機制
擴容時空間大小變化 hashmap中,雜湊桶陣列table的長度length大小必須為2的n次方 一定是合數 這是一種非常規的設計,常規的設計是把桶的大小設計為素數。相對來說素數導致衝突的概率要小於合數,具體證明可以參考 hashtable初始化桶大小為11,就是桶大小設計為素數的應用 hashta...
HashMap擴容機制
當map元素容量超過設定的閾值threshold capacity loadfactor時進行擴容,如下圖所示 原理 建立更大容量的新陣列,重新計算每個元素在新陣列中的位置進行遷移。缺點 每個元素需要重新計算hash 鍊錶中元素順序每次遷移後被倒置 原理 在擴充hashmap的時候,不需要像jdk1...
Java ArrayList擴容機制
底部採用動態陣列實現資料增加,刪除。size arraylist的實際存放資料個數,即我們常說的list長度,size 函式 elementdate elementdate,arraylist實際存放資料的陣列,可動態擴容,我們所說的就是動態改變elementdate.length,從而達到擴容,實...