API文档可以得到HashMap的以下几个特点:

  • 基于哈希表(hash table)实现,并且是链式哈希表
  • 允许空值和空键(null=null 键值对)
  • HashMap与Hashtable基本相同,区别是HashMap是非同步、非线程安全的,并且可以支持空值
  • HashMap是无序的:HashMap不保证元素的顺序,也不保证元素的顺序会保持不变
  • O(1)的时间效率:它对get和put基本操作提供了常数时间(constant-time)的性能
  • 影响HashMap性能的两个参数:初始化容量和负载因子(load factor)。不要把初始化容量设的太大,也不要把负载因子设的太小 。为了更好地权衡时间和空间消耗,默认的负载因子一般为0.75。默认的容量是16。
  • 当哈希表里的entry(键值对)超过一定阈值(threshold=capacity*factor)时,哈希表会进行再哈希(rehash)。再哈希后的哈希表的桶的个数之前的两倍 。

使用选择

Hashtable 从jdk1.0就有了,而HashMap是jdk1.2添加了,ConcurrentHashMap在jdk1.5才提供。

Hashtable和ConcurrentHashMap都是线程安全的。但是ConcurrentHashMap是1.5添加的更高级的并发工具。它使用了分段锁技术来实现更细粒度的同步。因此ConcurrentHashMap比Hashtable效率较高,因此在多线程情况下一般使用ConcurrentHashMap。而HashMap是非线程安全的,因此一般在单线程下使用。

优先选择:多线程访问:ConcurrentHashMap。单线程访问:HashMap

验证

写个简单易懂的代码作为例子,代码如下,然后分别在有注释的两行代码前设置断点:

public class HashMapL {

	public static void main(String[] args) {
HashMap<Integer, Integer> hashMap = new HashMap<>();
hashMap.put(null, null); //test null key and null value;
for(int i=0; i<16; i++){
hashMap.put(i, i); //autoboxing
} }

以debug模式运行上面代码可以看出HashMap<Integer, Integer> hashMap = new HashMap<>();初始化了如下的hashMap:

从上图可以看到,负载因子loadfactor默认值是0.75。注意,threshold现在的值时0。根据HashMap源码里面的注释可以知道,这个值是在给table分配空间后才会计算threshold的值,分配前它的值是0,而现在table的值为null,尚未分配。那么这里的table是什么呢?了解拉链式哈希表的人就会轻易知道它是一个链表数组。

按F6执行下一步,给hashMap赋值,并且是空值,来验证与Hashtable的区别:可以保存空值。

从上图可以看到,

  1. 现在table已经初始化了,它现在拥有一个元素 "null=null"(从图片最下面可以看成)。
  2. 它是一个包含16个元素的Node<k,v>类型数组
  3. 记住,现在table的id=24,可以和之后进行再哈希后的tableid对比。

继续按F6,直到size=threshold=12,此刻table的id和之前的一样,还是id=24

现在再按一次F6执行下一步,向hashMap里添加一个元素,让元素的总数size大于阈值threshold

从图片中看到,table的id=104,大小为32,阈值threshold=24。而之前的id=24,大小为16,threshold=12。因此得出结论,

当元素大小size大于阈值threshold时就会进行再哈希。再哈希后,HashMap就会自动扩容为之前的2倍。并且用一个新的对象代替原来的对象。
由此也可得知,自动扩容是需要消耗资源的,要尽量减少自动扩容的发生。

参考:

API文档

How HashMap works in java,强烈推荐!

(之前看了这篇文章感觉真的太好了,有种自己不用写了感觉。所以这篇博文最主要的目的是总结下HashMap的特点。和这篇文章的debug思路)

Java集合框架(Collection Framework)学习之 HashMap的更多相关文章

  1. Java集合框架Collection

    转自:http://www.cdtarena.com/javapx/201306/8891.html [plain] view plaincopyprint?01.在 Java2中,有一套设计优良的接 ...

  2. java集合框架(一):HashMap

    有大半年没有写博客了,虽然一直有在看书学习,但现在回过来看读书基本都是一种知识“输入”,很多时候是水过无痕.而知识的“输出”会逼着自己去找出没有掌握或者了解不深刻的东西,你要把一个知识点表达出来,自己 ...

  3. java集合框架(Collections Framework)

    */ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...

  4. 集合框架源码学习之HashMap(JDK1.8)

    目录: 0-1. 简介 0-2. 内部结构分析 0-2-1. JDK18之前 0-2-2. JDK18之后 0-3. LinkedList源码分析 0-3-1. 构造方法 0-3-2. put方法 0 ...

  5. java集合框架collection(6)继承结构图

    根据<java编程思想>里面的说法,java集合又叫容器,按照单槽和双槽分为两类,Collection和Map,这两个都是接口. 一.Collection Collection下面又分了三 ...

  6. JAVA集合框架 - Collection

    collection大致介绍 Collection是集合层次结构中的根接口. 集合表示一组对象.有些集合允许重复元素,有些则不允许.有些是有序的,有些是无序的. JDK没有提供此接口的任何直接实现:它 ...

  7. java集合框架collection(4)HashMap和Hashtable的区别

    HashMap和Hashtable的区别 HashMap和Hashtable都实现了Map接口,但决定用哪一个之前先要弄清楚它们之间的分别.主要的区别有:线程安全性,同步(synchronizatio ...

  8. java集合框架collection(5)HashMap和TreeMap

    上图转载自:http://www.cnblogs.com/vamei/archive/2013/04/15/3000913.html 一.区别和联系 1.迭代器 迭代器是一种设计模式,它是一个对象,它 ...

  9. java集合框架collection(3)Set、List和Map

    Set.List和Map是java collection中最常用的三种数据结构. Set是集合,不允许有重复的元素,List是动态数组实现的列表,有序可重复,Map是key-value的键值对,用于快 ...

  10. java集合框架collection(2)ArrayList和LinkedList

    ArrayList是基于动态数组实现的list,而LinkedList是基于链表实现的list.所以,ArrayList拥有着数组的特性,LinkedList拥有着链表的特性. 优缺点 ArrayLi ...

随机推荐

  1. Spring Boot实践——SpringMVC视图解析

    一.注解说明 在spring-boot+spring mvc 的项目中,有些时候我们需要自己配置一些项目的设置,就会涉及到这三个,那么,他们之间有什么关系呢? 首先,@EnableWebMvc=Web ...

  2. ffmpeg最简单的解码保存YUV数据 <转>

    video的raw data一般都是YUV420p的格式,简单的记录下这个格式的细节,如有不对希望大家能指出.   YUV图像通常有两种格式,一种是packet 还有一种是planar    从字面上 ...

  3. python算法之归并排序

    归并排序 归并排序是采用分治法的一个非常典型的应用.归并排序的思想就是先递归分解数组,再合并数组. 将数组分解最小之后,然后合并两个有序数组,基本思路是比较两个数组的最前面的数,谁小就先取谁,取了后相 ...

  4. tornado异步编程

    说明 以下的例子都有2个url,一个是耗时的请求,一个是可以立刻返回的请求,,我们希望的是访问立刻返回结果的请求不会被其他耗时请求影响 非异步处理 现在我们请求sleep然后同时请求justnow,发 ...

  5. Custom Draw 基础(转载)

    common control 4.7版本介绍了一个新的特性叫做Custom Draw,这个名字显得模糊不清,让人有点摸不着头脑,而且MSDN里也只给出了一些如风的解释和例子,没有谁告诉你你想知道的,和 ...

  6. Docker入门命令备份

    1.安装Docker curl -sSL https://get.docker.com/ | sh 2.将当前用户加入Docker用户组,这样就不用每次执行docker 命令时加上sudo了 3.查看 ...

  7. Elasticsearch-PHP 安装

    安装 Elasticsearch-PHP只有三个要求你需要担心: PHP 5.3.9 或更高版本(查看更多信息) Composer ext-curl: Libcurl的PHP扩展 其它的依赖会通过Co ...

  8. JDBC模板对象是多例的

  9. [hdu1823]Luck and Love(二维线段树)

    解题关键:二维线段树模板题(单点修改.查询max) #include<cstdio> #include<cstring> #include<algorithm> # ...

  10. 解剖Nginx·模块开发篇(3)ngx_http_hello_world_module 模块的基本函数实现

    还记得我们定义过一个结构体如下吗? typedef struct { ngx_str_t output_words; } ngx_http_hello_world_loc_conf_t; 它就是 He ...