arraylist 的構造問題:
1 構造指定容量的物件
2 構造empty物件
3 從乙個collection構造物件
看前兩個,預設構造和帶容量構造。看過原始碼後可以發現。
不指定容量的話,預設構造乙個length是10的object陣列(jdk8是乙個空陣列)。
然後每add一次,判斷是不是需要擴容了。是的話,擴1/2。
為方便計算我們假設可以宣告的陣列的最大長度是21億整,大於21億就認為溢位。
每擴大1/2達到乙個大1/2的數字。
如,放11個元素,此時容量會是15。下一次是15 + (15 >> 1) ,依次是22,33,
49,73………..直到大於21億時溢位。
會出現的問題:
1、 很極端的情況下乙個arraylist可能無法使用的空間最多是7億 -1。因為容量在14億 + 1時再擴容會溢位。這時候是明明有空間供擴容,但是表示arraylist容量的int值已經溢位了。
2、 由於陣列宣告後長度不可變。所以每次庫容都是new乙個是原來3/2的陣列,
然後舊的拷貝到新的。每次擴容都浪費3/2的空間。
3、 自動管理的容量很有可能不會完全用完,比如有5個元素,容量會是10;
有12個元素,容量會是15;有16個時,是22。已占用的空間浪費率最大是
(新容量 - (舊容量 + 1)) / 新容量。如:add 11個元素時:
(15 - (10 + 1d) )/ 15 = 0.26666666。舊容量越大,這個值越接近於1/3,浪費率越大。
只要是以陣列形式實現的,都應該提供自定義容量的方法,否則是不合常理的。
還有常用的stringbuilder、hashmap等最好盡量指定初始容量。
stringbuilder時 * 2 + 1;hashmap是大於等於指定的容量的最小的2的n次方數,
為的是尋找分組時,使用 &運算——i % 2^n 與 i & (2^n -1)相等。
hashmap擴容時更大的乙個2^n,stingbuilder是當前容量 * 2再加2,空間占用都
遠大於arraylist。
比如遍歷乙個使用者列表,把手機號拼接為乙個【手機號,手機號,手機號】的字串,
這時候由於list.size()和手機號長度已知,可以直接給stringbuilder指定初始容量。
並且很多情況下放入hashmap的k都是已知的,比如用於方法返回值的map:
此時的k數量是已知的,所以初始容量可以指定2,並且此時的」msg」
和」isok」很可能不會有hash衝突,所以裝載率引數也最好不用預設的0.75f而是1。
即使兩個k會產生hash衝突也無所謂,一是僅2條資料不至於對效率產生影響,二
是此處用map明顯是想返回多個值,而不是用的hash查詢特性。
內部陣列實現的都要盡量指定初始容量。
好多人用arraylist不管放幾個還是幾百上千個東西,都是用預設無參構造。
用hashmap不管是兩個還是幾十個也是用無參構造。
具體加不加初始容量的記憶體占用區別,可以用freememory()看一下。
類似**都是不會出現問題,但是一旦出問題就是outofmemory,然後一群人在那喊「優化」,想想就好笑,連個陣列形式容器加容量引數都不知道的人,也可以喊「優化」。我是不明白他們理解的優化到底是做什麼。還有就是,你既然有能力去優化,為什麼不一開始就做好,而是出了問題後來彌補。
關於ArrayList初始化時,初始容量的問題
首先來看arraylist的構造方法有哪些 一 arraylist的構造方法 無參構造 傳入指定引數 這個暫時不用管 在arraylist中有乙個elementdate的陣列,arraylist底層就是用object陣列來實現的 這裡還定義了乙個空陣列,在arraylist使用無參構造方法時使用 回...
集合的初始容量與效能
沒事隨便寫寫 你知道當你寫下下面這兩句時這些資料結構的實際長度嗎?arraylist list new arraylist hashtable table new hastable 你知道初始容量對今後的操作有什麼效能上的影響嗎?如果你不知道,讓我來告訴你,因為我研究過了。arraylist與lis...
STL Vector容量問題
1 clear,erase pop back 函式只刪除物件,並沒有釋放vec中的記憶體,若物件是指標還需要delete 2 在erase,clear,pop back 刪除物件的後,size改變,capacity保持不變,所以push back也是在capacity範圍內進行插入新物件,當插入的資...