HashMap中傻傻分不清楚的那些概念

作者:CQITer小编 时间:2018-05-27 09:11

字号
人工智能+区块链的发展趋势及应用调研报告

很多人在通过阅读源码的方式学习Java,这是个很好的方式。而JDK的源码自然是首选。在JDK的众多类中,我觉得HashMap及其相关的类是设计的比较好的。很多人读过HashMap的代码,不知道你们有没有和我一样,觉得HashMap中关于容量相关的参数定义的太多了,傻傻分不清楚。

HashMap中傻傻分不清楚的那些概念

其实,这篇文章介绍的内容比较简单,只要认真的看看HashMap的原理还是可以理解的,单独写一篇文章的原因是因为我后面还有几篇关于HashMap源码分析的文章,这些概念不熟悉的话阅读后面的文章会很吃力。

HashMap中重要的成员变量

先来看一下,HashMap中都定义了哪些成员变量。

HashMap中傻傻分不清楚的那些概念

上面是一张HashMap中主要的成员变量的图,其中有一个是我们本文主要关注的: size、loadFactor、threshold、DEFAULT_LOAD_FACTOR和DEFAULT_INITIAL_CAPACITY。

我们先来简单解释一下这些参数的含义,然后再分析他们的作用。

HashMap类中有以下主要成员变量:

transient int size; 

记录了Map中KV对的个数

loadFactor 

装载印子,用来衡量HashMap满的程度。loadFactor的默认值为0.75f(static final float DEFAULT_LOAD_FACTOR = 0.75f;)。

int threshold; 

临界值,当实际KV个数超过threshold时,HashMap会将容量扩容,threshold=容量*加载因子

除了以上这些重要成员变量外,HashMap中还有一个和他们紧密相关的概念:capacit

容量,如果不指定,默认容量是16(static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;)

可能看完了你还是有点蒙,size和capacity之间有啥关系?为啥要定义这两个变量。loadFactor和threshold又是干啥的?

size 和 capacity

HashMap中的size和capacity之间的区别其实解释起来也挺简单的。我们知道,HashMap就像一个“桶”,那么capacity就是这个桶“当前”最多可以装多少元素,而size表示这个桶已经装了多少元素。来看下以下代码:

Map<String, String> map = new HashMap<String, String>(); 

map.put("hollis""hollischuang"); 

 

Class<?> mapType = map.getClass(); 

Method capacity = mapType.getDeclaredMethod("capacity"); 

capacity.setAccessible(true); 

System.out.println("capacity : " + capacity.invoke(map)); 

 

Field size = mapType.getDeclaredField("size"); 

size.setAccessible(true); 

System.out.println("size : " + size.get(map)); 

我们定义了一个新的HashMap,并想其中put了一个元素,然后通过反射的方式打印capacity和size。输出结果为:capacity : 16、size : 1

默认情况下,一个HashMap的容量(capacity)是16,设计成16的好处我在《全网把Map中的hash()分析的最透彻的文章,别无二家。》中也简单介绍过,主要是可以使用按位与替代取模来提升hash的效率。

为什么我刚刚说capacity就是这个桶“当前”最多可以装多少元素呢?当前怎么理解呢。其实,HashMap是具有扩容机制的。在一个HashMap第一次初始化的时候,默认情况下他的容量是16,当达到扩容条件的时候,就需要进行扩容了,会从16扩容成32。

我们知道,HashMap的重载的构造函数中,有一个是支持传入initialCapacity的,那么我们尝试着设置一下,看结果如何。

Map<String, String> map = new HashMap<String, String>(1); 

map.put("hahaha""hollischuang"); 

 

Class<?> mapType = map.getClass(); 

Method capacity = mapType.getDeclaredMethod("capacity"); 

capacity.setAccessible(true); 

System.out.println("capacity : " + capacity.invoke(map)); 

 

Map<String, String> map = new HashMap<String, String>(7); 

map.put("hahaha""hollischuang"); 

 

Class<?> mapType = map.getClass(); 

Method capacity = mapType.getDeclaredMethod("capacity"); 

capacity.setAccessible(true); 

System.out.println("capacity : " + capacity.invoke(map)); 

 

 

Map<String, String> map = new HashMap<String, String>(9); 

map.put("hahaha""hollischuang"); 

 

Class<?> mapType = map.getClass(); 

Method capacity = mapType.getDeclaredMethod("capacity"); 

capacity.setAccessible(true); 

System.out.println("capacity : " + capacity.invoke(map)); 

分别执行以上3段代码,分别输出:capacity : 2、capacity : 8、capacity : 16。

责任编辑:CQITer新闻报料:400-888-8888   本站原创,未经授权不得转载
关键词 >>HashMap Java JDK
继续阅读
热新闻
推荐
关于我们联系我们免责声明隐私政策 友情链接