今天上午在CSDN的論壇里看到有朋友提的問題如下:
- /** @param maxSize Maximum sum of the sizes of the Bitmaps in this cache */
- public LruMemoryCache(int maxSize) {
- if (maxSize <= 0) {
- throw new IllegalArgumentException("maxSize <= 0");
- }
- this.maxSize = maxSize;
- this.map = new LinkedHashMap<String, Bitmap>(0, 0.75f, true);
- }
上面這段代碼是github上面一個比較有名的開源項目中的一段,大概就是一個用LinkedHashMap來實現lru,我的問題LinkedHashMap構造函數的前2個參數,初始容量竟然是0?那加載因子0.75有何意義?據我所知,擴展容量時,是用初始容量*加載因子,這樣的話,這個擴展的容量不是始終都是0了嗎,初始也為0,擴展也為0,那這個hashmap還有何意義?不知道哪里理解錯了
第一個網友的回答如下:
你再看看HashMap的源代碼,看看是怎么擴容的。
上面這段代碼沒有什么特別的地方,只是初始化了一個長度為0的HashMap,順便設置了LinkedHashMap的訪問順序(第三個參數), 這種情況一般是創建時不確定Map中是否會有值及幾個值,比較保守的寫法,不想浪費空間。
默認的構造方法是長度為16, 如果你不確定map中是否能放夠16個鍵值,那么16的長度就浪費了。這樣寫也有不利的地方,多了幾次運行時的擴容操作,作者可能認為空間更重要吧。
第二個網友的回答如下:
看看源碼就知道了
其實第一個參數是你要設置的初始大小;而程序內部實際的初始大小是1;
如果你設置的初始大小(initialCapacity)小於1, 那么map大小就是默認的1;
否則會不斷左移(乘2)直到capacity大於你設置的initialCapacity;
- public LinkedHashMap(int initialCapacity,
- float loadFactor,
- boolean accessOrder) {
- super(initialCapacity, loadFactor);//這里調用父類HashMap的構造方法;
- this.accessOrder = accessOrder;
- }
- public HashMap(int initialCapacity, float loadFactor) {
- if (initialCapacity < 0)
- throw new IllegalArgumentException("Illegal initial capacity: " +
- initialCapacity);
- if (initialCapacity > MAXIMUM_CAPACITY)
- initialCapacity = MAXIMUM_CAPACITY;
- if (loadFactor <= 0 || Float.isNaN(loadFactor))
- throw new IllegalArgumentException("Illegal load factor: " +
- loadFactor);
- // Find a power of 2 >= initialCapacity
- int capacity = 1; // 默認是1
- while (capacity < initialCapacity)//不斷翻倍直到大於人為設置的大小
- capacity <<= 1;
- this.loadFactor = loadFactor;
- threshold = (int)(capacity * loadFactor);//的確如你所言,后面如果需要增大長度,按照capacity*loadFactor取整后增長;
- table = new Entry[capacity];
- init();
- }
上面的兩位網友的答復其實都已解答了發帖網友的疑問,第一位回復的網友顯然是翻看過LinkedHashMap類的源碼的。我寫這篇博文目的在於記錄分享,因為我之前在翻看Android 開源框架Universal-Image-Loader(在github上的地址:https://github.com/nostra13/Android-Universal-Image-Loader)里的那段源碼時,也是不太明白作者意欲何為?當時沒深究,今天上午在論壇里看到發帖的網友的提問及兩位網友的答復,覺得這個問題有必要記錄下。