HashMap 初始化时 容量设定

问题引入

注:本文代码源自java 9

  • 阿里的插件对于初始化HashMap时,调用无参构造方法,提示如下:

  • 那么问题来了,如果已知需要向 map 中 put n次,那么需要设定初始容量为多少?
  • 单纯的我今天上午还认为是合理的容量是 n + 1 即可,直到看了源码;
  • 应注意,map.size 获取的是当前map中键值对的个数,而不是容量。

当初始化的时候,没有指定容量,情况如何?

1.直接调用如下构造函数(无参)

    /**
     * Constructs an empty {@code HashMap} with the default initial capacity
     * (16) and the default load factor (0.75).
     */
    public HashMap() {
        this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
    }
  • 首先应该清楚,loadFactor 是 装载因子(通俗来讲,若值为0.5f,那么当map元素达到 容量*0.5f的时候,就应该做扩容等操作)
  • HashMap对象实际上只有 threshold(临界值,阈值) 属性,每次put()后,需要比较的是阈值与size(map中已有键值对的个数)
  • 至于容量属性,实际上各个方法中用的是 transient Node<K,V>[] table; 中 table 的长度

    具体可参考 http://www.importnew.com/20386.html

  • 其次,作为一个没有被赋值的全局变量,在类的构造函数中必须要赋值。
  • 本构造方法上说明:构造了一个空的HashMap,默认容量为16,装载因子为0.75。
  • 然而可以清楚地看到,此构造方法只是将常量 DEFAULT_LOAD_FACTOR赋值给装载因子,但没有设定容量。
  • 当调用put()时,如下方式设定了初始容量。
  • 调用 putVal(hash(key), key, value, false, true)
public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }
  • 在putVal()中,进入第一个if,调用resize()
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
               boolean evict) {
    Node<K,V>[] tab; Node<K,V> p; int n, i;
    if ((tab = table) == null || (n = tab.length) == 0)
        n = (tab = resize()).length;
   //省略无关代码
}
  • 在下方代码中,oldCap 与 oldThr 初始都为0,故直接进入else{}
final Node<K,V>[] resize() {
    Node<K,V>[] oldTab = table;
    int oldCap = (oldTab == null) ? 0 : oldTab.length;
    int oldThr = threshold;
    int newCap, newThr = 0;
    if (oldCap > 0)
       //省略无关代码
    else if (oldThr > 0) // initial capacity was placed in threshold
        //省略无关代码
    else {               // zero initial threshold signifies using defaults
        newCap = DEFAULT_INITIAL_CAPACITY;//设定 newCap  = 16
        newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);//设定 newThr  = 16 * 0.75 = 12
    }
        threshold = newThr;//将对象的 threshold(临界值,阈值) 属性设置为 newThr
            Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
        table = //将对象的 table 属性设置为刚实例化的 newTab
        //省略无关代码
        return newTab;//并返回
    
  • 综上,默认无参的构造方法设定初始容量为16,装载因子为0.75f。

当我们指定容量为n的时候,情况如何?

参考文章:http://blog.csdn.net/fan2012huan/article/details/51087722

原文地址:https://www.cnblogs.com/kangkaii/p/8471619.html

时间: 2024-08-29 05:40:13

HashMap 初始化时 容量设定的相关文章

Java 中 HashMap 初始化时赋值

1.HashMap 初始化的文艺写法 HashMap 是一种常用的数据结构,一般用来做数据字典或者 Hash 查找的容器.普通青年一般会这么初始化:HashMap<String, String> map = new HashMap<String, String>();map.put("name", "test");  map.put("age", "20"); 看完这段代码,很多人都会觉得这么写太啰嗦了

java在hashmap初始化时赋初值

Java中的HashMap是一种常用的数据结构,一般用来做数据字典或者Hash查找的容器. 一般我们初始化并赋初值是这样做的: HashMap<String, Object> map = new HashMap<>(); map.put("name", "yanggb"); map.put("lover", "huangq"); 但是有时候我们会想在一个表达式中完成初始化并赋初值的操作: HashMap

HashMap初始化容量过程

集合是Java开发日常开发中经常会使用到的,而作为一种典型的K-V结构的数据结构,HashMap对于Java开发者一定不陌生.在日常开发中,我们经常会像如下方式以下创建一个HashMap: Map<String, String> map = new HashMap<String, String>(); 但是,大家有没有想过,上面的代码中,我们并没有给HashMap指定容量,那么,这时候一个新创建的HashMap的默认容量是多少呢?为什么呢?本文就来分析下这个问题. 什么是容量 在J

Java中HashMap的初始容量设置

根据阿里巴巴Java开发手册上建议HashMap初始化时设置已知的大小,如果不超过16个,那么设置成默认大小16: 集合初始化时, 指定集合初始值大小. 说明: HashMap使用HashMap(int initialCapacity)初始化, 正例:initialCapacity = (需要存储的元素个数 / 负载因子) + 1.注意负载因子(即loader factor)默认为0.75, 如果暂时无法确定初始值大小,请设置为16(即默认值). 反例:HashMap需要放置1024个元素,由于

HashMap 中的容量与扩容实现,细致入微,值的一品!

前言 开心一刻 巴闭,你的脚怎么会有味道,我要闻闻看是不是好吃的,嗯~~爸比你的脚臭死啦!! …… 高手过招,招招致命 JDK1.8 中 HashMap 的底层实现,我相信大家都能说上来个 一二,底层数据结构 数组 + 链表(或红黑树) ,源码如下 /** * 数组 */ transient Node<K,V>[] table; /** * 链表结构 */ static class Node<K,V> implements Map.Entry<K,V> { final

百度地图初始化时设置地图的状态(转)

//初始化地图     MapView mMapView = (MapView) findViewById(R.id.map); BaiduMap mBaidumap = mMapView.getMap(); //设定中心点坐标 LatLng cenpt = new LatLng(29.806651,121.606983);          //定义地图状态         MapStatus mMapStatus = new MapStatus.Builder()         .targ

ios uiimage初始化时的两种方法

第一种方式:UIImage *image = [UIImage imageNamed:@"image"]; 使用这种方式,第一次读取的时候,先把这个图片存到缓存里,下次再使用时直接从缓存中读取:优点:只有第一次使用的时候稍慢,接下来在使用就会稍快:缺点:如果在当前工程中只使用一次会浪费内存. 第二种方式:initWithContentsOfFiles初始化时,每次都会根据路径去读取,不会占用内存,如果图片在当前工程中只使用一次,应该选择这个方法.

Java类静态属性、静态块、非静态属性、非静态块、构造函数在初始化时的执行顺序

前言 今天在看Android ContentProvider实现的时候,突然想到了Java类在new的过程中,静态域.静态块.非静态域.非静态块.构造函数的执行顺序问题.其实这是一个很经典的问题,非常考察对Java基础知识的掌握程度.很多面试过程中相信也有这样的问题,趁着周末有时间复习一下. 结论 这里先把整理好的结论抛给大家,然后我在写个程序来验证我们的结论.在Java类被new的过程中,执行顺序如下: 实现自身的静态属性和静态代码块.(根据代码出现的顺序决定谁先执行) 实现自身的非静态属性和

UIView(包括子类)的几个初始化时执行动作的时机

转载自:http://www.tqcto.com/article/mobile/56963.html 根据你需要执行的动作, 这里有几个方法: -(id)initWithFrame:(CGRect)frame - UIView的指定初始化方法; 总是发送给UIView去初始化, 除非是从一个nib文件中加载的; -(id)initWithCoder:(NSCoder *)coder - 从nib文件中加载的时候发送此消息给UIView; -(void)awakeFromNib - 在所有的nib