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

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实现原理

    在Java中,HashMap的初始化涉及两个重要属性:initialCapacity(初始容量)和loadFactor(负载因子)。initialCapacity定义了HashMap的初始大小,而loadFactor定义了在何时进行扩容的阈值。默认情况下,...

    hashmap使用实例

    1. **初始化**:可以无参数或指定容量和加载因子初始化HashMap。例如: ```java HashMap, String&gt; map = new HashMap(); HashMap, String&gt; map2 = new HashMap(16, 0.75f); ``` 2. **添加元素**:使用`put()`...

    面试必考之HashMap源码分析与实现

    HashMap在创建时会初始化一个默认容量(16)和负载因子(0.75)。当元素数量达到当前容量与负载因子的乘积时,HashMap会自动进行扩容,通常新容量为原容量的两倍。这个过程涉及到数组的复制,可能会带来一定的性能...

    HashMap源码分析

    - **初始化散列表**:创建大小为`capacity`的`Entry[]`数组作为散列表,并设置`useAltHashing`标志以决定是否启用替代散列算法。 #### 四、总结 `HashMap`通过结合数组和链表(或红黑树)的数据结构,在保持高效的...

    HashMap之put方法源码解读.docx

    可以看到,putVal 方法首先判断 table 数组是否为空,如果为空,则调用 resize 方法将其初始化。resize 方法会将 table 数组的容量和阈值都扩大为原来的2倍。 接下来,putVal 方法会根据 key 的hashCode计算出要...

    自定义map实现java的hashmap

    - 初始化数据结构:使用数组作为基础存储结构,因为数组可以通过索引来直接访问元素,速度很快。但由于哈希冲突的存在,我们还需要一个链表或红黑树来处理冲突。 - 计算哈希码:对于输入的键,我们需要调用其...

    hashMap工具类

    这个构造函数初始化一个新的`HashMap`实例,并调用`clear`方法来清除内部存储的数据。这样做的目的是确保每次创建新的`HashMap`实例时,它都是空的、干净的状态。 ##### `clear`: 清除所有条目 `public function ...

    HashMap与HashTable和HashSet的区别

    - **初始化**:初始化`HashSet`时可以指定初始容量,例如`new HashSet(17)`。 #### 五、总结 综上所述,`HashTable`、`HashMap`和`HashSet`各有其特点和适用场景: - 如果需要线程安全,并且不允许`key`或`value`...

    深入理解Java之HashMap —— 03

    初始化时,HashMap并不会立即创建数组,而是先计算阈值threshold,它是容量的负载因子倍数。threshold的计算使用了tableSizeFor()函数,确保其为2的幂次方。 2. **tableSizeFor()函数**: 这个静态函数接收一个...

    词法分析器java

    构造函数`public analyetest()`初始化了所有的`HashMap`和`ArrayList`对象。这些对象用于存储词法分析过程中识别出来的各种符号。 ##### 2.3 初始化方法 - **init()**: 调用四个子方法来初始化不同类型的符号。 - ...

    Java集合系列之HashMap源码分析

    HashMap的构造函数包括HashMap(int initialCapacity, float loadFactor),它传入初始化容量和加载因子作为参数,如果初始化容量小于0将抛出异常,如果初始化容量大于最大容量就把它设为最大容量。 HashMap的Entry是...

    Java源码角度分析HashMap用法

    HashMap是一个动态变长的数据结构,在使用HashMap的时候,为了提高执行效率,我们往往会设置HashMap初始化容量: ```java Map,String&gt; rm=new HashMap,String&gt;(2) ``` 或者使用guava的工具类Maps,可以很方便的创建...

    2022年Java中对HashMap的深度分析Java教程.docx

    本教程将深入分析2022年Java中HashMap的内部机制、关键属性和操作。 HashMap的核心属性包括容量(capacity)和负载因子(load factor)。容量是指HashMap可以存储的元素的最大数量,而负载因子则是HashMap在达到多...

    HashMap 源码分析

    HashMap的全局变量定义了其核心参数,包括默认初始容量(16)、最大容量(2^30)、默认负载因子(0.75)以及树化和去树化的阈值(分别为8和6)。负载因子定义了在达到多大比例的填满时应该进行扩容,而树化和去树化...

    HashMap put方法的源码分析

    1. 如果数组`table`为空,这意味着HashMap尚未初始化,putVal会触发`resize()`方法进行初始化,创建一个大小为16的新数组。 2. 根据key的哈希值计算出对应的数组索引`i`。如果该位置的数组元素为null,直接将新节点`...

    HashMap常见面试题,简述以及对源码操作分析

    初始化长度为16LoadFactor:负载因子,默认值为0.75f 6. 扩容的步骤 扩容分为两步:扩容:创建一个新的Entry空数组,长度是原数组的2倍。ReHash:遍历原Entry数组,把所有的Entry重新Hash到新数组。 7. 为什么要重新...

    java提高篇(二三)-----HashMap.pdf

    初始化容量是哈希表中桶的数量,加载因子衡量了HashMap在自动扩容前能有多满。默认的加载因子0.75是一个平衡空间利用率和查找效率的折衷选择。 3. **数据结构** HashMap的核心数据结构是“链表散列”,即数组与...

    c语言 hashmap

    初始化哈希表时,需要为数组和链表分配内存。同时,为了防止内存泄漏,插入和删除元素后记得释放不再使用的内存。 5. **跨平台兼容性**:为了使哈希表能在Windows和Linux上运行,需要注意以下几点: - 文件操作:...

    逆向-音乐学家方大刚-快速定位hashMap

    3. **数据流分析**:通过跟踪函数间的调用关系和数据流动,理解HashMap的结构是如何被初始化、更新和查询的。这可能涉及到对指针解引用、内存布局的理解以及动态分析。 4. **哈希函数分析**:HashMap的关键在于它的...

Global site tag (gtag.js) - Google Analytics