關於HashMap、HashSet和ArrayList集合對象容量初始值設置及擴容演示


ArrayList:
-------------------------------------
明確知道容量:直接設置初始容量,如new ArrayList<>(100)
無法確定容量:預估一個比較接近的值,如果實在無法確定,則無需指定初始值 (有默認值)
ArrayList沒有加載因子,初始容量10,擴容增量為原來的0.5倍取整


HashMap(HashSet規則相同)
-------------------------------------
HashMap的默認加載因子為0.75,但可以使用構造器指定,如new HashMap<>(100, 1),此時指定加載因子為1
故計算HashMap的初始值時的工式為:(int) (realSize / loadFactor) + 1

如果實際容量為100,加載因子為默認(0.75),計算容量為:(int) (100 / 0.75) + 1 = 134,則實例化HashMap為 new HashMap<>(134)  (注意:由於HashMap的容量必須為2的N次方,故此時HashMap的實際容量為256)
如果實際容量為100,加載因子1,則計算工式為:(int) (100 / 1) + 1 = 101,則則實例化HashMap為 new HashMap<>(101, 1)   (注意:由於HashMap的容量必須為2的N次方,故此時HashMap的實際容量為128)
HashMap、HashMap加載因子0.75,初始容量16,擴容增量為原來的1倍
注意:加載因子越大節省內存但查找效率低,加載因子越小耗內存但查找效率高,系統默認加載因子為0.75,一般情況下我們是無需修改的。

//以下為計算HashMap的實際容量

//計算容量。
int capacity = (int) (realSize / loadFactor) + 1;
//必須為2的N次方並進行上舍入。
int pow = (int)Math.ceil( Math.log(capacity) / Math.log(2.0));
//返回2的N次方為實際容量。
return (int) Math.pow(2, pow);

 

 

以上單元測試HashMap、ArrayList持續增加元素及擴容情況:

    @Test
    public void testHashMapResize() throws Exception {
        System.out.println("-------- 開始測試HashMap --------");
        System.out.println("不設置 initCapacity");
        this.testHashMapResizeProfile(0);
        System.out.println("");
        System.out.println("initCapacity 為 25");
        this.testHashMapResizeProfile(25);
        System.out.println("");
        System.out.println("initCapacity 為 34");
        this.testHashMapResizeProfile(34);

        System.out.println();
        System.out.println("-------- 開始測試ArrayList --------");
        System.out.println("不設置 initCapacity");
        this.testArrayListResizeProfile(0);
        System.out.println("");
        System.out.println("initCapacity 為 25");
        this.testArrayListResizeProfile(25);
    }

    /**
     * 以循環添加25個元素測試擴容。
     * @param initCapacity 初始容量
     * @throws Exception
     */
    private void testHashMapResizeProfile(int initCapacity) throws Exception {
        Map<String, String> map = null;
        if (initCapacity <= 0) {
            map = new HashMap();
        } else {
            map = new HashMap(initCapacity);
        }

        Field threshold = map.getClass().getDeclaredField("threshold");
        Field size = map.getClass().getDeclaredField("size");
        Method capacity = map.getClass().getDeclaredMethod("capacity");

        threshold.setAccessible(true);
        size.setAccessible(true);
        capacity.setAccessible(true);

        // 臨界值、容量測試
        for (int i = 1; i <= 25; i++) {
            map.put(String.valueOf(i), i + "**");
            System.out.println("第" + i + "個對象, size為" + size.get(map) + ", threshold為" + threshold.get(map) + ", capacity容量為" + capacity.invoke(map));
        }
    }

    /**
     * 以循環添加25個元素測試擴容。
     * @param initCapacity 初始容量
     * @throws Exception
     */
    private void testArrayListResizeProfile(int initCapacity) throws Exception {
        ArrayList<String> list = null;
        if (initCapacity <= 0) {
            list = new ArrayList();
        } else {
            list = new ArrayList(initCapacity);
        }

        Field size = list.getClass().getDeclaredField("size");
        Field elementData = list.getClass().getDeclaredField("elementData");

        size.setAccessible(true);
        elementData.setAccessible(true);

        // 臨界值、容量測試
        for (int i = 1; i <= 25; i++) {
            list.add(String.valueOf(i));
            System.out.println("第" + i + "個對象, size為:" + size.get(list) + ", 擴容后容量為:" + ((Object[])elementData.get(list)).length);
        }
    }

 

以下為HashMap持續增加元素及擴容輸出:

不設置 initCapacity
第1個對象, size為1, threshold為12, capacity容量為16
第2個對象, size為2, threshold為12, capacity容量為16
第3個對象, size為3, threshold為12, capacity容量為16
第4個對象, size為4, threshold為12, capacity容量為16
第5個對象, size為5, threshold為12, capacity容量為16
第6個對象, size為6, threshold為12, capacity容量為16
第7個對象, size為7, threshold為12, capacity容量為16
第8個對象, size為8, threshold為12, capacity容量為16
第9個對象, size為9, threshold為12, capacity容量為16
第10個對象, size為10, threshold為12, capacity容量為16
第11個對象, size為11, threshold為12, capacity容量為16
第12個對象, size為12, threshold為12, capacity容量為16
第13個對象, size為13, threshold為24, capacity容量為32
第14個對象, size為14, threshold為24, capacity容量為32
第15個對象, size為15, threshold為24, capacity容量為32
第16個對象, size為16, threshold為24, capacity容量為32
第17個對象, size為17, threshold為24, capacity容量為32
第18個對象, size為18, threshold為24, capacity容量為32
第19個對象, size為19, threshold為24, capacity容量為32
第20個對象, size為20, threshold為24, capacity容量為32
第21個對象, size為21, threshold為24, capacity容量為32
第22個對象, size為22, threshold為24, capacity容量為32
第23個對象, size為23, threshold為24, capacity容量為32
第24個對象, size為24, threshold為24, capacity容量為32
第25個對象, size為25, threshold為48, capacity容量為64
注意:擴容2次

initCapacity 為 25
第1個對象, size為1, threshold為24, capacity容量為32
第2個對象, size為2, threshold為24, capacity容量為32
第3個對象, size為3, threshold為24, capacity容量為32
第4個對象, size為4, threshold為24, capacity容量為32
第5個對象, size為5, threshold為24, capacity容量為32
第6個對象, size為6, threshold為24, capacity容量為32
第7個對象, size為7, threshold為24, capacity容量為32
第8個對象, size為8, threshold為24, capacity容量為32
第9個對象, size為9, threshold為24, capacity容量為32
第10個對象, size為10, threshold為24, capacity容量為32
第11個對象, size為11, threshold為24, capacity容量為32
第12個對象, size為12, threshold為24, capacity容量為32
第13個對象, size為13, threshold為24, capacity容量為32
第14個對象, size為14, threshold為24, capacity容量為32
第15個對象, size為15, threshold為24, capacity容量為32
第16個對象, size為16, threshold為24, capacity容量為32
第17個對象, size為17, threshold為24, capacity容量為32
第18個對象, size為18, threshold為24, capacity容量為32
第19個對象, size為19, threshold為24, capacity容量為32
第20個對象, size為20, threshold為24, capacity容量為32
第21個對象, size為21, threshold為24, capacity容量為32
第22個對象, size為22, threshold為24, capacity容量為32
第23個對象, size為23, threshold為24, capacity容量為32
第24個對象, size為24, threshold為24, capacity容量為32
第25個對象, size為25, threshold為48, capacity容量為64
注意:擴容1次

initCapacity 為 34   (int) (25 / 0.75) + 1 = 34
第1個對象, size為1, threshold為48, capacity容量為64
第2個對象, size為2, threshold為48, capacity容量為64
第3個對象, size為3, threshold為48, capacity容量為64
第4個對象, size為4, threshold為48, capacity容量為64
第5個對象, size為5, threshold為48, capacity容量為64
第6個對象, size為6, threshold為48, capacity容量為64
第7個對象, size為7, threshold為48, capacity容量為64
第8個對象, size為8, threshold為48, capacity容量為64
第9個對象, size為9, threshold為48, capacity容量為64
第10個對象, size為10, threshold為48, capacity容量為64
第11個對象, size為11, threshold為48, capacity容量為64
第12個對象, size為12, threshold為48, capacity容量為64
第13個對象, size為13, threshold為48, capacity容量為64
第14個對象, size為14, threshold為48, capacity容量為64
第15個對象, size為15, threshold為48, capacity容量為64
第16個對象, size為16, threshold為48, capacity容量為64
第17個對象, size為17, threshold為48, capacity容量為64
第18個對象, size為18, threshold為48, capacity容量為64
第19個對象, size為19, threshold為48, capacity容量為64
第20個對象, size為20, threshold為48, capacity容量為64
第21個對象, size為21, threshold為48, capacity容量為64
第22個對象, size為22, threshold為48, capacity容量為64
第23個對象, size為23, threshold為48, capacity容量為64
第24個對象, size為24, threshold為48, capacity容量為64
第25個對象, size為25, threshold為48, capacity容量為64
注意:未擴容 

 

以下為ArrayList持續增加元素及擴容輸出:

不設置 initCapacity
第1個對象, size為:1, 擴容后容量為:10
第2個對象, size為:2, 擴容后容量為:10
第3個對象, size為:3, 擴容后容量為:10
第4個對象, size為:4, 擴容后容量為:10
第5個對象, size為:5, 擴容后容量為:10
第6個對象, size為:6, 擴容后容量為:10
第7個對象, size為:7, 擴容后容量為:10
第8個對象, size為:8, 擴容后容量為:10
第9個對象, size為:9, 擴容后容量為:10
第10個對象, size為:10, 擴容后容量為:10
第11個對象, size為:11, 擴容后容量為:15
第12個對象, size為:12, 擴容后容量為:15
第13個對象, size為:13, 擴容后容量為:15
第14個對象, size為:14, 擴容后容量為:15
第15個對象, size為:15, 擴容后容量為:15
第16個對象, size為:16, 擴容后容量為:22
第17個對象, size為:17, 擴容后容量為:22
第18個對象, size為:18, 擴容后容量為:22
第19個對象, size為:19, 擴容后容量為:22
第20個對象, size為:20, 擴容后容量為:22
第21個對象, size為:21, 擴容后容量為:22
第22個對象, size為:22, 擴容后容量為:22
第23個對象, size為:23, 擴容后容量為:33
第24個對象, size為:24, 擴容后容量為:33
第25個對象, size為:25, 擴容后容量為:33
注意:擴容2次
initCapacity 為 25
第1個對象, size為:1, 擴容后容量為:25
第2個對象, size為:2, 擴容后容量為:25
第3個對象, size為:3, 擴容后容量為:25
第4個對象, size為:4, 擴容后容量為:25
第5個對象, size為:5, 擴容后容量為:25
第6個對象, size為:6, 擴容后容量為:25
第7個對象, size為:7, 擴容后容量為:25
第8個對象, size為:8, 擴容后容量為:25
第9個對象, size為:9, 擴容后容量為:25
第10個對象, size為:10, 擴容后容量為:25
第11個對象, size為:11, 擴容后容量為:25
第12個對象, size為:12, 擴容后容量為:25
第13個對象, size為:13, 擴容后容量為:25
第14個對象, size為:14, 擴容后容量為:25
第15個對象, size為:15, 擴容后容量為:25
第16個對象, size為:16, 擴容后容量為:25
第17個對象, size為:17, 擴容后容量為:25
第18個對象, size為:18, 擴容后容量為:25
第19個對象, size為:19, 擴容后容量為:25
第20個對象, size為:20, 擴容后容量為:25
第21個對象, size為:21, 擴容后容量為:25
第22個對象, size為:22, 擴容后容量為:25
第23個對象, size為:23, 擴容后容量為:25
第24個對象, size為:24, 擴容后容量為:25
第25個對象, size為:25, 擴容后容量為:25
注意:沒有擴容 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM