zoukankan      html  css  js  c++  java
  • Java集合框架(Collection Framework)学习之 HashMap

    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思路)

  • 相关阅读:
    第一章 002-JDK的安装
    第一章 001-初识Java
    计算2^4000内数字0到9的分布
    1027 大数乘法
    1005 大数加法
    哈夫曼编码
    new: Set up a window
    GLFW扩展库
    outdated: 3.Adding Color
    简单的图元
  • 原文地址:https://www.cnblogs.com/averey/p/4363266.html
Copyright © 2011-2022 走看看