HashMap的相关笔记----创建HashMap

      HashMap是我们开发中常用的一个容器。但是通常情况下,创建HashMap所采用的策略莫过于一句“new HashMap()”。然而,Java本身提供了除空参以外的其他两种方法。分别是:

HashMap(int initialCapacity) 
          构造一个带指定初始容量和默认加载因子 (0.75) 的空 HashMap。 
HashMap(int initialCapacity, float loadFactor) 
          构造一个带指定初始容量和加载因子的空 HashMap。 
HashMap(Map<? extends K,? extends V> m) 
          构造一个映射关系与指定 Map 相同的新 HashMap。 

        这三个方法中,除第三种以外,都说明了构造一个指定初始容量的参数---initialCapacity。HashMap默认创建的初始容量是16,而此处的参数指定了初始容量的大小。但最终创建的容量是否为我们所指定的大小?做个例子。首先是默认构造:

	Map<String, Object> hashMap = new HashMap<String, Object>();
	Field field = HashMap.class.getDeclaredField("DEFAULT_INITIAL_CAPACITY");
	field.setAccessible(true);
	System.out.println(field.get(hashMap));

        查看控制台输出可以看见输出值为16。当然,直接查看源代码也能看到这个初始变量的定义。那么我们再换个方案,指定初始容量为9试试。

	Map<String, Object> hashMap = new HashMap<String, Object>(9);
	Field field = HashMap.class.getDeclaredField("threshold");
	field.setAccessible(true);
	int threshold = (Integer)field.get(hashMap);
	System.out.println(threshold/0.75);

        这里再看,发现输出值为16而非9。此外,为何这次获取容量会使用threshold/0.75的方案?这里需要解释下。threshold的值是HashMap在初始化过程中赋予的,目的是为了当HashMap中键值对数量达到一定标准时进行拓容。而此处的threshold就是这个标准。它的计算方案为:threshold=当前容量*当前加载因子。加载因子因为没有指定,默认即为0.75,因此,当前容量即为threshold/当前加载因子(0.75)。得出答案为16。

        为什么我们指定了初始容量为9,而构造出来的结果却是16呢?跟入HashMap的初始化代码处看到如下内容:

    public HashMap(int initialCapacity) {
        this(initialCapacity, DEFAULT_LOAD_FACTOR);
    }

    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;
        while (capacity < initialCapacity)
            capacity <<= 1;

        this.loadFactor = loadFactor;
        threshold = (int)(capacity * loadFactor);
        table = new Entry[capacity];
        init();
    }

        解读之后发现。我们默认设定的初始容量其实并不是实际容量大小,实际容量大小是由capacity决定的。而这个变量的值初始为1,通过

        while (capacity < initialCapacity)
            capacity <<= 1;

这个方法来计算。此时就变成了

capacityinitialCapacitycapacity < initialCapacity
19true
29true
49true
89true
169false
       

         于是乎,最后初始化所得到的容量为16。原因就是因为capacity这个变量的增长运算采用的左移运算。而非直接采用capacity=initialCapacity的方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值