`
darrenzhu
  • 浏览: 806920 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

为什么HashMap容量一定要为2的幂呢?

阅读更多
原文链接:https://blog.csdn.net/wanghuan220323/article/details/78242449
做为面试常考的问题之一,每次都答的模模糊糊,有必要了解一下,首先来看一下hashmap的put方法的源码

public V put(K key, V value) { 
        if (key == null)                 
            return putForNullKey(value);     //将空key的Entry加入到table[0]中 
        int hash = hash(key.hashCode());     //计算key.hashcode()的hash值,hash函数由hashmap自己实现 
        int i = indexFor(hash, table.length);//获取将要存放的数组下标 
        /*
         * for中的代码用于:当hash值相同且key相同的情况下,使用新值覆盖旧值(其实就是修改功能)
         */ 
        for (Entry<K, V> e = table[i]; e != null; e = e.next) {//注意:for循环在第一次执行时就会先判断条件 
            Object k; 
            //hash值相同且key相同的情况下,使用新值覆盖旧值 
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { 
                V oldValue = e.value; 
                e.value = value; 
                //e.recordAccess(this); 
                return oldValue;//返回旧值 
            } 
        } 
         
        modCount++; 
        addEntry(hash, key, value, i);//增加一个新的Entry到table[i] 
        return null;//如果没有与传入的key相等的Entry,就返回null 
    } 

    /**
     * "按位与"来获取数组下标
     */ 
    static int indexFor(int h, int length) { 
        return h & (length - 1); 
    } 

hashmap始终将自己的桶保持在2的n次方,这是为什么?indexFor这个方法解释了这个问题

大家都知道计算机里面位运算是基本运算,位运算的效率是远远高于取余%运算的

举个例子:2^n转换成二进制就是1+n个0,减1之后就是0+n个1,如16 -> 10000,15 -> 01111

那么根据&位运算的规则,都为1(真)时,才为1,那0≤运算后的结果≤15,假设h <= 15,那么运算后的结果就是h本身,h >15,运算后的结果就是最后四位二进制做&运算后的值,最终,就是%运算后的余数。

当容量一定是2^n时,h & (length - 1) == h % length

分享到:
评论

相关推荐

    HashMap的容量为什么必须是2的幂?

    当使用带容量参数的构造函数创建HashMap时,传入的容量会被调整为大于等于该值的最小的2的幂。例如,如果传入的容量是10,实际上HashMap会将容量设置为16。这种做法的背后有以下几个原因: 1. **高效索引计算**:...

    HashMap夺命连环问面试题分享给需要同学.docx

    追问:为什么HashMap的数组长度要取2的整数幂? 6.讲一下HashMap中的哈希函数时怎么实现的? 追问:哈希函数为什么这么设计? 7.HashMap是线程安全的吗? 追问:如何解决这个线程不安全的问题? 追问:分别讲一下这...

    HashMap介绍和使用

    **2.2 为什么数组长度为2的幂时效率最高** 假设数组长度为16(2的4次方),如两个键的哈希值分别为8和9,进行按位与操作后结果相同(均为0),这会导致哈希碰撞。因此,8和9会存放在数组的同一位置,形成链表。 ...

    HashMap和HashTable的区别和不同

    - 当负载因子超过0.75时,`HashMap`会自动扩容,新的容量为原来的两倍。这种扩容策略有助于保持良好的性能。 - **HashTable**: - 默认大小为11。`HashTable`不对指定的初始容量进行特殊处理,因此可能不是2的幂。...

    HashMap的数据结构

    3. **容量**:HashMap的容量是数组的大小,必须是2的幂。这是因为哈希函数的结果需要通过位运算(与操作)来确定索引,确保均匀分布。初始容量通常为16,随着元素增加,容量会翻倍增长。 4. **并发问题**:HashMap...

    java中hashmap容量的初始化实现

    为什么要设置HashMap的初始化容量?在《阿里巴巴Java开发手册》中,有一条开发建议是建议我们设置HashMap的初始化容量。这是因为HashMap的扩容机制。当HashMap中的元素个数超过临界值(Threshold)时,HashMap就会...

    HashMap源码分析

    - **确定容量**:为了提高散列表的性能,`HashMap`要求容量必须为2的幂。因此,这里通过循环左移的方式找到最接近`initialCapacity`的2的幂。 - **设置属性**:初始化`loadFactor`和`threshold`属性,`threshold`...

    HashMap类

    1. **容量(Capacity)**:HashMap的容量是指它的桶的数量,默认为16,且必须是2的幂次方。 2. **负载因子(Load Factor)**:负载因子是HashMap在达到多满时开始扩容的比例,默认为0.75。当桶中的元素数量达到容量...

    Hashtable和HashMap区别

    而`HashMap`的默认初始容量是16,并且是以2的幂次方进行增长。这意味着`HashMap`在容量管理上更加高效,因为它能够更好地利用内存空间,减少扩容操作。 ### MVC模式简介 MVC(Model-View-Controller)模式是一种...

    HashMap扩容时的rehash方法中(e.hash & oldCap) == 0算法推导.docx

    `oldCap`是旧数组(即当前HashMap的容量)的长度,由于HashMap的容量必须是2的幂次方,所以`oldCap`的二进制表示中,最高位为1,其余位可能为0。 `(e.hash & oldCap) == 0`这个条件用于判断元素在新数组中的索引...

    HashMap底层原理

    HashMap内部维护了一个Entry数组,初始容量为16,并且总是保持为2的幂。当插入新元素时,如果计算出的哈希码对应的数组位置已经有元素存在,那么就会发生哈希冲突。为了解决冲突,HashMap采用了链地址法,即将冲突的...

    HashMap 概述 精讲 .md

    - **长度限制**:解释为什么HashMap的长度通常是2的幂次方。 - **线程安全实现**:列举几种使HashMap线程安全的方法。 以上知识点涵盖了HashMap的主要方面,有助于深入理解其工作原理和应用场景。在准备面试或进行...

    深入理解Java之HashMap —— 03

    通过一系列位运算,将cap的所有低bit设置为1,然后与自身进行按位或操作,这样可以将小于最高bit的其他bit也设为1,最终使结果变为下一个2的幂。如果cap已经是2的幂,这个操作会使cap加1,以避免返回原值。 3. **...

    HashMap源码粗略解读(面试必问)

    HashMap的内部结构是一个数组配合链表的数据结构,数组的大小必须是2的幂,原因在于HashMap使用了与运算(`hash & (length - 1)`)来确定元素在数组中的位置。这是因为2的幂具有对称性,可以确保所有可能的哈希值均匀...

    HASHMAP结构及版本区别.docx

    HashMap在创建时有初始容量的概念,默认为16,且必须是2的幂。这是因为HashMap使用了位运算来计算元素在数组中的位置,只有当容量是2的幂时,位运算才能保证效率。加载因子是衡量哈希表何时扩容的一个参数,默认为...

    HashMap的实现原理

    从JDK 1.8开始,引入了红黑树(Red-Black Tree)优化,当链表长度达到一定阈值(默认为8)时,链表会转换为红黑树,以提供更高效的查找性能。 2. **哈希方法** HashMap使用`key.hashCode()`生成初始哈希值,并通过...

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

    - 当HashMap初始化时,会创建一个大小为2的n次幂的数组,以确保所有索引都能均匀分布。这个大小由初始容量决定,并且会调整到大于初始容量的最小2的n次幂。 4. **扩容机制** - 当HashMap的容量达到“阈值”(容量...

    HashMap-hash原理

    - **改善位掩码的影响**:当哈希表的长度为2的幂时,位掩码会导致高位的变化不直接影响低位,从而可能导致某些高位不同的键最终映射到相同的槽中。通过位扩展操作,可以确保高位的信息也能影响到低位,进而影响到...

    HashMap.md

    在`HashMap`中,数组的长度总是2的幂次方,这是因为`HashMap`在计算存储位置时会使用哈希码和数组长度进行**按位与(&)**运算。为了确保哈希值能均匀分布在整个数组范围内,数组长度必须是2的幂次方。这样可以避免...

Global site tag (gtag.js) - Google Analytics