理解HashMap

转载 2012年03月22日 10:51:25
以前学习HahsMap都是粗略的了解一下,能够用就行了。这次对HahsMap的源代码看了几遍,对此有一定的理解,就我的理解我总结出如下几点。但在此之前,我们先说下HahsMap的结构,简单来说:HahsMap其实是一个数组和链表的结合体。 
第一、首先对HahsMap的初始容量(也即DEFAULT_INITIAL_CAPACITY)来说个事,看下面的代码吧: 
Java代码  收藏代码
  1. public class TestHashMap {  
  2.     public static void main(String[] args) {  
  3.         HashMap<Integer, Integer> hm1=new HashMap<Integer, Integer>();  
  4.         HashMap<Integer, Integer> hm2=new HashMap<Integer, Integer>(1024<<7);  
  5.         long time1=System.currentTimeMillis();    
  6.         for(int i=0;i<100000;i++){  
  7.             hm1.put(i, i);  
  8.         }  
  9.         long time2=System.currentTimeMillis();    
  10.         long time3=System.currentTimeMillis();    
  11.         for(int i=0;i<100000;i++){  
  12.             hm2.put(i, i);  
  13.         }  
  14.         long time4=System.currentTimeMillis();   
  15.         System.out.println("默认初始容量8所用时间为:"+(time2-time1));  
  16.         System.out.println("定义初始容量131072所用时间为:"+(time4-time3));  
  17.     }  
  18. }  

程序运行的结果为:默认初始容量8所用时间为:94 
               定义初始容量131072所用时间为:47 
可以看出,第二种方法所用时间基本上是前面的一半,这是为什么呢?其实,HashMap的rehash是一个非常消耗性能的操作,rehash的次数越多,所消耗的时间也就越长。当插入100000个元素时,使用初始容量rehash的次数会很多,而根据(100000)/0.75=133333(0.75是HashMap的默认装填因子),也即是说第二种方法只要rehash一次即可,所以消耗的时间会大大减少。 
第二、HashMap的装填因子,按如上代码,我们稍做修改,把定义的hm1和hm2修改成如下: 
Java代码  收藏代码
  1. HashMap<Integer, Integer> hm1=new HashMap<Integer, Integer>(1024<<7,1);  
  2.         HashMap<Integer, Integer> hm2=new HashMap<Integer, Integer>(1024<<7);  
在此运行,结果为:定义装填因子为1所用时间为:47 
               默认装填因子为0.75所用时间为:62 
在这里,我们循环插入100000个数据,但根据HashMap中的hash()函数,基本呈均匀分布,这样,没有什么冲突,那当然是装满更好,插入的效率会提高。但并不是装填因子越大越好,因为我们并不知道插入的数据是不是接近于均匀分布,如果不是的话,那么冲突会很大,查询的效率就会降低,装填因子太小也不好,因为这样会很浪费空间。所以HashMap默认的装填因子取了个折中的数0.75。 
小结下:装填因子衡量的是一个散列表的空间使用程度,装填因子越大表示散列表的装填程度越高,反之越小。我们知道对一个链表法的散列表来说,查询一个元素的平均时间为O(1+a),因此,如果装填因子越大,对空间的利用更充分,然而查询效率就会降低;如果装填因子过小,那么散列表的数据就过于稀疏,对空间造成严重的浪费。 
总结下:如果你知道所要插入的数据的个数N,那么你可以定义HashMap的容量大小为:N/0.75,有因为HashMap的容量必须是2的幂次方,找一个接近的即可;如果你还知道其近似一个均匀分布的话,那么装填因子也可以自己定义,接近于1会更效率。

深入理解hashmap

  • 2017年01月06日 14:49
  • 953KB
  • 下载

hashMap的原理 深入理解

首先再次强调hashcode (==)和equals的真正含义(我记得以前有人会说,equals是判断对象内容,hashcode是判断是否相等之类): equals:是否同一个对象实例。注意,是...

Map 综述(一):彻头彻尾理解 HashMap

摘要:   HashMap是Map族中最为常用的一种,也是 Java Collection Framework 的重要成员。本文首先给出了 HashMap 的实质并概述了其与 Map、Has...

深入理解HashMap(及hash函数的真正巧妙之处)

原文地址:http://www.iteye.com/topic/539465   /**      *@author annegu      *@date 2009-12-02   ...

第一次写博客,谈谈对HashMap和Hashtable的区别理解

今天看到JAVA基础中有关于HashMap和Hashtable的区别,字面上比较笼统,因此决定具体进行了解。 Hashtable已经是个过时的集合类,在Java 4中被重写了,实现了Map接口,所...

HashMap之深入理解

HashMap实例中table的length是在初始化时就被指定的,无论采用默认值还是其他指定值,table数组的大小就已经确定,随着添加元素的增多在一定时机下下会对table数组进行扩容呢。   ...
  • ls5718
  • ls5718
  • 2016年06月29日 19:26
  • 2835

hashMap的原理 深入理解

首先再次强调hashcode (==)和equals的真正含义(我记得以前有人会说,equals是判断对象内容,hashcode是判断是否相等之类): equals:是否同一个对象实例。注意,是“实...

从源码理解HashMap

package java.util; import java.io.IOException; import java.io.InvalidObjectException; import java.i...
  • ymrfzr
  • ymrfzr
  • 2016年04月25日 17:47
  • 1763

深入理解hashmap的resize

什么是resize? resize就是重新计算容量;向HashMap对象里不停的添加元素,而HashMap对象内部的数组无法装载更多的元素时,对象就需要扩大数组的长度,以便能装入更多的元素;当然ja...

Java中HashMap和TreeMap的区别深入理解

首先介绍一下什么是Map。在数组中我们是通过数组下标来对其内容索引的,而在Map中我们通过对象来对对象进行索引,用来索引的对象叫做key,其对应的对象叫做value。这就是我们平时说的键值对。 Ha...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:理解HashMap
举报原因:
原因补充:

(最多只允许输入30个字)