`
donlianli
  • 浏览: 336440 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
Group-logo
Elasticsearch...
浏览量:216639
社区版块
存档分类
最新评论

HashMap初始化参数剖析

阅读更多

HashMap除了有无参的构造方法(默认会构造出一个默认为16的数组及loadFactor=0.75的HashMap)外,也可以在New  HaspMap的时候指定这两个值。原构造方法声明如下:

HashMap(int initialCapacity, float loadFactor) 
          Constructs an empty HashMap with the specified initial capacity and load factor.

 

第一个参数:initialCapacity,初始化容量。

第二个参数:loadFactor,重新加载比例。即当Map的容量小于initialCapacity*loadFactor的时候,进行扩容。扩容就意味着重新申请更大的内存,对原来的数据进行重hash。显然是一件很浪费时间的问题。

 

 

通常情况下,我们可能需要将一个List里面的东西,转化成一个HashMap来进行进一步的运算。这个时候,我们可以调用List.size获得元素的数量,这样,我们就可以在构造一个HashMap的时候就指定他的大小。

比如:

Map<Long,Object> data = new HashMap<Long,Object>(list.size,1f)

 我们认为,这样初始化化HashMap就会省去中间Map因默认的16数组不够导致的resize和rehash,性能会高点。

 

 

你可能会认为,如果你这样写,初始化容量就是list.size。

 那你就大错特错了。我们看看HashMap的源码:

 // Find a power of 2 >= initialCapacity
        int capacity = 1;
        while (capacity < initialCapacity)
            capacity <<= 1; //此处的意思就是不断的加倍扩展
        this.loadFactor = loadFactor;
        threshold = (int)Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
        table = new Entry[capacity];

 从代码可以看出,hashMap的大小只可能是2,4,8,16,32,128,....1024......等大小,也就是2的n次方大小,如果你的list里面不幸是129个元素,那么HashMap就会创建一个256的数组。就是这么悲催。

不过,指定大小肯定比不知道大小,性能要高点。

 

为啥hash的数组非得要2的n次方呢?因为Hashmap进行hash后取数组坐标的时候是这样运算的。
  static int indexFor(int h, int length) {
        return h & (length-1);
    }
 
如果length为非2的n次方。比如是3,那么3-1的二进制位0010,其hash后的坐标除了table[2]外,其他的都hash到table[0]上面了。
也就是说,如果非2的n次方的话,hash定位的时候冲突就会成倍增长。
综上所述,我们在使用HashMap的时候,如果知道hash的key的数量的话,尽量指定hash的initialCapacity和loadFactor。这样能够提高性能。另外,loadFactor,理想情况下1是最好的,因为你已经知道总大小,如果hash的算法足够好的话,正好能够将所有的值都无冲突的hash到正确位置,这样的话不用resize;如果hash算法算法不够好,冲突多,那么数组肯定有剩余,也不用再resize。
 

好了,写这个纯粹为一时兴起。但这个同时也引起了我对另一个问题的探索,就是String的hashcode重复的概率。

因为String的hashcode,代码是这样:

public int hashCode() {
int h = hash;//默认0
if (h == 0) {
    int off = offset;//默认0
    char val[] = value;//字符串是用字符数组表示的.
    int len = count;//字符串长度
            for (int i = 0; i < len; i++) {
                h = 31*h + val[off++];
            }
            hash = h;
        }
        return h;
 }

 

 

哪个问题,我就再写一篇吧。

 

参考资料:

http://blog.csdn.net/sgbfblog/article/details/7580510

 

 

 

请支持原创:

http://donlianli.iteye.com/blog/1978237

 

 

 

 

 

对这类话题感兴趣?欢迎发送邮件至donlianli@126.com
关于我:邯郸人,擅长Java,Javascript,Extjs,oracle sql。
更多我之前的文章,可以访问 我的空间

 

3
0
分享到:
评论
2 楼 donlianli 2013-11-21  
jahu 写道
请你去看下,hashmap的api,,说的什么啊。随便弄一点东西出来就写。有意思吗?

有理解错误的,欢迎指出。你说的hashmap的api指得是什么?
1 楼 jahu 2013-11-21  
请你去看下,hashmap的api,,说的什么啊。随便弄一点东西出来就写。有意思吗?

相关推荐

    面试官!你又双叒叕问HashMap!

    文章目录HashMap的数据结构(图解+源码分析)数组单链表HashMap如何插入数据(图解+源码分析pos)为什么初始化容量是2的倍数(源码分析)HashMap如何解决Key冲突(图解+源码分析)HashMap如何扩容(源码分析)...

    java8集合源码分析-Outline:大纲

    静态块(初始化块 构造函数 ) 静态内部类() 静态导包 final() transient() foreach循环原理() volatile底层实现() equals和hashcode(, ) string,stringbuffer和stringbuilder(,,,, ) 伪泛型(, , ) 自动装箱(,) Try-...

    leetcode下载-LruCache:实现LRU算法的Cache类

    之前分析过Lru算法的实现方式:HashMap+双向链表,参考链接: 这里主要介绍Android SDK中LruCache缓存算法的实现. 构造函数 LruCache只有一个构造函数,并且有一个必传参数: public LruCache(int maxSize) { if (maxSize...

    突破程序员基本功的16课.part2

    1.1 数组初始化 1.1.1 Java数组是静态的 1.1.2 数组一定要初始化吗 1.1.3 基本类型数组的初始化 1.1.4 引用类型数组的初始化 1.2 使用数组 1.2.1 数组元素就是变量 1.2.2 没有多维数组 1.3 小结 第2课 ...

    sesvc.exe 阿萨德

    由于给定的 HashMap 的容量大小是固定的,比如默认初始化: public HashMap() { this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR); } public HashMap(int initialCapacity, float loadFactor) { if ...

    resha-turkish-stemmer:一种快速且攻击性较低的 Java 土耳其语词干分析器

    词干分析器类是单例的,线程安全的,并且是惰性初始化的 ####用法 //it is implemented as an enum to guarantee //a singleton, thread safe and lazy initialized object Stemmer stemmer = Resha.Instance;...

    疯狂JAVA讲义

    5.3.2 成员变量的初始化和内存中的运行机制 128 5.3.3 局部变量的初始化和内存中的运行机制 130 5.3.4 变量的使用规则 130 5.4 隐藏和封装 132 5.4.1 理解封装 132 5.4.2 使用访问控制符 132 5.4.3 package和...

    Javascript中Array用法实例分析

    本文实例讲述了Javascript中Array用法。...//创建数组对象,无需初始化长度,动态 citys[0] = '上海'; citys[1] ='北京'; citys[2] = '深圳'; for(var i=0; i&lt; citys.length; i++){ alert&#40;citys[i]&#41;; }

    Golang中Set类型的实现方法示例详解

    无非是Set不能含有重复的Item的特性,Set有初始化、Add、Clear、Remove、Contains等操作。接下来看具体的实现方式分析吧。 实现 仍然按照已有的编程经验来联想如何实现基本Set功能,在Java中很容易知道HashSet的...

    工程硕士学位论文 基于Android+HTML5的移动Web项目高效开发探究

    市场上相应的检测平台诸如检测通、凡特网等皆为pc端检测网站,并且操作繁琐不够人性化,用户在实地使用中存在很多问题。昆山工业技术研究院着眼于为委托用户和质检机构搭建良好的沟通桥梁,免去目前市场业务中企业...

    javaSE代码实例

    5.3.2 利用循环初始化 64 5.3.3 枚举初始化 66 5.4 数组的相互赋值 67 5.4.1 基本类型数组赋值规则 67 5.4.2 引用型数组赋值规则 68 5.5 数组的常用操作 69 5.5.1 数组复制 69 5.5.2 数组排序 71 ...

    超级有影响力霸气的Java面试题大全文档

    多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。 5、String是最基本的数据类型吗?  基本数据类型包括byte、int、char、long、...

    java 面试题 总结

    多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。 2、String是最基本的数据类型吗? 基本数据类型包括byte、int、char、long、float、...

    Java NIO 聊天室 JSwing

    * 获得一个Socket通道,并对该通道做一些初始化的工作 * @param ip 连接的服务器的ip * @param port 连接的服务器的端口号 * @throws IOException */ public void initClient(String ip,int port) throws...

    JAVA入门1.2.3:一个老鸟的JAVA学习心得 PART1(共3个)

    7.9.3 留个无参数的构造方法——给重要属性赋初始值 183 7.9.4 在构造方法中调用构造方法 184 7.10 方法大汇总 185 7.10.1 本例中用到的类 186 7.10.2 使用例程将本章的知识穿起来 189 7.11 小结:多方位理解...

    Java入门1·2·3:一个老鸟的Java学习心得.PART3(共3个)

    7.9.3 留个无参数的构造方法——给重要属性赋初始值 183 7.9.4 在构造方法中调用构造方法 184 7.10 方法大汇总 185 7.10.1 本例中用到的类 186 7.10.2 使用例程将本章的知识穿起来 189 7.11 小结:多方位理解...

    JAVA核心知识点整理(有效)

    可达性分析............................................................................................................................................... 26 2.3.2. 2.3.3. 老年代 ........................

    java核心知识点整理.pdf

    可达性分析............................................................................................................................................... 26 2.3.2. 2.3.3. 老年代 ........................

Global site tag (gtag.js) - Google Analytics