澳门新葡亰娱乐网站-www.142net-欢迎您

澳门新葡亰娱乐网站是因为你还没有找到一条正确的致富之路,www.142net是将所有的游戏都汇集在一起的官方平台,因为澳门新葡亰娱乐网站这个网站当中有着大量的游戏攻略,托IP定位技术,传达终端直接到达的精准传播方式。

HashMap的实现原理,的实现原理

来源:http://www.bhtsgq.com 作者:计算机知识 人气:168 发布时间:2019-05-30
摘要:HashMap完结原理 xpj手机娱乐中心,HashMap的最底层使用数组 链表/红黑树落成。 transient NodeK,V[] table; 那意味HashMap是Node数组构成,当中Node类的得以实现如下,能够看来那实质上便是个链表

HashMap完结原理

xpj手机娱乐中心,HashMap的最底层使用数组 链表/红黑树落成。

transient Node<K,V>[] table;那意味HashMap是Node数组构成,当中Node类的得以实现如下,能够看来那实质上便是个链表,链表的种种结点是3个<K,V>映射。

static class Node<K,V> implements Map.Entry<K,V> {
    final int hash;
    final K key;
    V value;
    Node<K,V> next;
}

HashMap的各类下标都存放了一条链表。

哈希表的为主便是数组。比如大家要新扩充或查究有些成分,大家经过把当前因素的首要字通过某些函数映射到数组中的有个别地方,通过数组下标贰次定位就可实现操作。

HashMap 概述

HashMap 是依靠哈希表的 Map 接口的非同步完成。此实现提供具有可选的照射操作,并允许行使 null 值和 null 键。此类不保障映射的相继,特别是它不保障该每一种永世不改变。

此达成假定哈希函数将元素适本地遍及在各桶之间,可为基本操作(get 和 put)提供稳定的习性。迭代 collection 视图所需的时光与 HashMap 实例的“容积”(桶的数目)及其大小(键-值映射关周密)成比例。所以,即便迭代质量很关键,则毫不将伊始体积设置得太高或将加载因子设置得太低。只怕大家初阶对这段话有好几不太懂,不过并非忧郁,当你读完这篇小说后,就会深刻精通那中间的意思了。

亟需注意的是:Hashmap 不是一块的,假诺八个线程同一时间做客一个HashMap,而里边至少一个线程从组织上(指增添也许去除一个或五个映射关系的任何操作)修改了,则必须保持外部同步,以免止对映射举行意外的非同步访问。

常量/变量定义

/* 常量定义 */

// 初始容量为16
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
// 最大容量
static final int MAXIMUM_CAPACITY = 1 << 30;
// 负载因子,当键值对个数达到DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR会触发resize扩容
static final float DEFAULT_LOAD_FACTOR = 0.75f;
// 当链表长度大于8,且数组长度大于MIN_TREEIFY_CAPACITY,就会转为红黑树
static final int TREEIFY_THRESHOLD = 8;
// 当resize时候发现链表长度小于6时,从红黑树退化为链表
static final int UNTREEIFY_THRESHOLD = 6;
// 在要将链表转为红黑树之前,再进行一次判断,若数组容量小于该值,则用resize扩容,放弃转为红黑树
// 主要是为了在建立Map的初期,放置过多键值对进入同一个数组下标中,而导致不必要的链表->红黑树的转化,此时扩容即可,可有效减少冲突
static final int MIN_TREEIFY_CAPACITY = 64;

/* 变量定义 */

// 键值对的个数
transient int size;
// 键值对的个数大于该值时候,会触发扩容
int threshold;
// 非线程安全的集合类中几乎都有这个变量的影子,每次结构被修改都会更新该值,表示被修改的次数
transient int modCount;

关于modCount的法力见这篇blog

在1个迭代器初阶的时候会赋予它调用这一个迭代器的靶子的modCount,如何在迭代器遍历的经过中,1旦发觉那么些指标的modCount和迭代器中贮存的modCount差别等那就抛分外。
Fail-Fast机制:java.util.HashMap不是线程安全的,由此即使在行使迭代器的进度中有此外线程修改了map,那么将抛出ConcurrentModificationException,那正是所谓fail-fast攻略。那壹安插在源码中的实现是通过modCount域,modCount看名就会猜到其意义正是修改次数,对HashMap内容的改造都将扩大这么些值,那么在迭代器早先化进程中会将那些值赋给迭代器的expectedModCount。在迭代历程中,决断modCount跟expectedModCount是或不是等于,假诺不对等就表示曾经有别的线程修改了Map。

留意起先体积和扩容后的体量都必须是贰的次幂,为啥吗?

存储位置 = f(关键字)
HashMap 的数据结构

在 Java 编制程序语言中,最主旨的布局正是二种,四个是数组,其余叁个是指针(引用),HashMap 正是经过那三个数据结构进行落到实处。HashMap实际上是三个“链表散列”的数据结构,即数组和链表的结合体。

xpj手机娱乐中心 1

image.png

从上海体育地方中得以见见,HashMap 底层正是贰个数组结构,数组中的每壹项又是三个链表。当新建二个 HashMap 的时候,就能初叶化三个数组。

大家通过 JDK 中的 HashMap 源码举行部分上学,首先看一下构造函数:

public HashMap(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: "  
                                               initialCapacity);
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal load factor: "  
                                               loadFactor);

        // 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];
        useAltHashing = sun.misc.VM.isBooted() &&
                (capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
        init();
}

咱们第三看一下第 1八 行代码table = new Entry[capacity];。这不正是 Java 中数组的创建格局吧?也等于说在构造函数中,其创制了一个 Entry 的数组,其大小为 capacity(近期大家还没有要求太了解该变量含义),那么 Entry 又是如何组织吧?看一下源码:

static class Entry<K,V> implements Map.Entry<K,V> {
    final K key;
    V value;
    Entry<K,V> next;
    final int hash;
    ……
}

咱俩近期依然只珍视宗旨的片段,Entry 是多个 static class,个中饱含了 key 和 value,相当于键值对,此外还隐含了3个 next 的 Entry 指针。大家能够总计出:Entry 便是数组中的成分,每个 Entry 其实正是3个key-value 对,它具备一个针对性下三个因素的引用,那就构成了链表。

hash方法

先看散列方法

static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

HashMap的散列方法如上,其实就是将hash值的高十六个人和低十六人异或,大家将马上来看hash在与n

  • 壹相与的时候,高位的音信也被怀想了,能使碰撞的概率减小,散列得更均匀。

在JDK 8中,HashMap的putVal方法中有如此一句

if ((p = tab[i = (n - 1) & hash]) == null)
    tab[i] = newNode(hash, key, value, null);

HashMap的实现原理,的实现原理。重大就是那句(n - 1) & hash,这行代码是把待插入的结点散列到数组中有个别下标中,个中hash正是通过下面的章程的获取的,为待插入Node的key的hash值,n是table的体量即table.length,2的次幂用2进制表示的话,唯有最高位为一,别的为都是0。减去一,刚好就反了回复。比方1陆的二进制表示为10000,减去一后的二进制表示为0111壹,除了最高位别的各位都是1,保险了在相与时,能够使得散列值分布得更均匀(因为壹旦某位为0举个例子十11,那么结点长久不会被散列到111一以此任务),且当n为二的次幂时候有(n - 1) & hash == hash % n, 举个例证,比方hash等于陆时候,01111和001十相与正是001拾,hash等于1陆时,相与就等于0了,多举几个例证便得以表明那1结论。最后来答复为何HashMap的容积要一贯维持2的次幂

  • 使散列值布满均匀
  • 位运算的频率比取余的效能高

留意table.length是数组的容积,而transient int size代表存入Map中的键值对数。

int threshold代表临界值,当键值对的个数大于临界值,就能扩大容积。threshold的换代是由上边包车型客车办法成功的。

static final int tableSizeFor(int cap) {
    int n = cap - 1;
    n |= n >>> 1;
    n |= n >>> 2;
    n |= n >>> 4;
    n |= n >>> 8;
    n |= n >>> 16;
    return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n   1;
}

该情势重回大于等于cap的小小的叁遍幂数值。举个例子cap为1陆,就回到1陆,cap为一柒就回到32。

里头,这一个函数f一般称为哈希函数,那么些函数的设计好坏会直接影响到哈希表的三六玖等。比方,比如大家要在哈希表中实行插入操作:

HashMap 的为主措施解读

put方法

put方法首要由putVal方法达成:

  • 只要未有生出hash争论,直接在数组tab[i = (n - 1) & hash]处新建一个结点;
  • 不然,产生了hash抵触,此时key借使和头结点的key一样,找到要翻新的结点,直接跳到最后去更新值
  • 不然,假设数组下标中的类型是TreeNode,就插入到红黑树中
  • 若果只是平凡的链表,就在链表中寻找,找到key一样的结点就跳出,到最终去更新值;到链表尾也尚无找到就在尾巴部分插入四个新结点。接着判别此时链表长度若高于8的话,还要求将链表转为红黑树(注意在要将链表转为红黑树从前,再实行贰回剖断,若数组体量小于该值,则用resize扩大体量,抛弃转为红黑树)

xpj手机娱乐中心 2

存储
/**
     * Associates the specified value with the specified key in this map.
     * If the map previously contained a mapping for the key, the old
     * value is replaced.
     *
     * @param key key with which the specified value is to be associated
     * @param value value to be associated with the specified key
     * @return the previous value associated with <tt>key</tt>, or
     *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
     *         (A <tt>null</tt> return can also indicate that the map
     *         previously associated <tt>null</tt> with <tt>key</tt>.)
     */
public V put(K key, V value) {
        //其允许存放null的key和null的value,当其key为null时,调用putForNullKey方法,放入到table[0]的这个位置
        if (key == null)
            return putForNullKey(value);
        //通过调用hash方法对key进行哈希,得到哈希之后的数值。该方法实现可以通过看源码,其目的是为了尽可能的让键值对可以分不到不同的桶中
        int hash = hash(key);
        //根据上一步骤中求出的hash得到在数组中是索引i
        int i = indexFor(hash, table.length);
        //如果i处的Entry不为null,则通过其next指针不断遍历e元素的下一个元素。
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            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);
        return null;
}

大家看一下方法的科班注释:在讲解中率先提到了,当我们 put 的时候,若是key 存在了,那么新的 value 会代替旧的 value,并且只要 key 存在的事态下,该方法再次回到的是旧的 value,纵然 key 不设有,那么重返 null。

从上边的源代码中得以见见:当我们往 HashMap 中 put 成分的时候,先依据 key 的 hashCode 重新计算 hash 值,依照 hash 值获得那么些成分在数组中的地点(即下标),假如数组该职位上早已存放有别的因素了,那么在那些岗位上的因素将以链表的样式存放,新参预的放在链头,初叶参与的放在链尾。假使数组该职位上尚未元素,就一向将该因素放到此数组中的该地方上。

addEntry(hash, key, value, i)方法依照测算出的 hash 值,将 key-value 对位于数组 table 的 i 索引处。addEntry 是 HashMap 提供的1个包访问权限的点子,代码如下:

/**
     * Adds a new entry with the specified key, value and hash code to
     * the specified bucket.  It is the responsibility of this
     * method to resize the table if appropriate.
     *
     * Subclass overrides this to alter the behavior of put method.
     */
void addEntry(int hash, K key, V value, int bucketIndex) {
        if ((size >= threshold) && (null != table[bucketIndex])) {
            resize(2 * table.length);
            hash = (null != key) ? hash(key) : 0;
            bucketIndex = indexFor(hash, table.length);
        }

        createEntry(hash, key, value, bucketIndex);
}
void createEntry(int hash, K key, V value, int bucketIndex) {
        // 获取指定 bucketIndex 索引处的 Entry
        Entry<K,V> e = table[bucketIndex];
        // 将新创建的 Entry 放入 bucketIndex 索引处,并让新的 Entry 指向原来的 Entr
        table[bucketIndex] = new Entry<>(hash, key, value, e);
        size  ;
}

当系统调整存款和储蓄 HashMap 中的 key-value 对时,完全没有设想 Entry 中的 value,仅仅只是遵照 key 来计量并调控每一种 Entry 的积累地点。大家一同能够把 Map 会集中的 value 当成 key 的直属,当系统调节了 key 的存款和储蓄地方然后,value 随之保存在这里就可以。

hash(int h)方法依据 key 的 hashCode 重新总括二次散列。此算法参预了高位计算,幸免未有不改变,高位变化时,形成的 hash 争辩。

final int hash(Object k) {
        int h = 0;
        if (useAltHashing) {
            if (k instanceof String) {
                return sun.misc.Hashing.stringHash32((String) k);
            }
            h = hashSeed;
        }
        //得到k的hashcode值
        h ^= k.hashCode();
        //进行计算
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
}

咱俩得以见见在 HashMap 中要找到有个别成分,必要基于 key 的 hash 值来求得对应数组中的地方。如何总计这一个地点正是 hash 算法。前边说过 HashMap 的数据结构是数组和链表的构成,所以大家本来愿意以此 HashMap 里面的成分地点尽量的布满均匀些,尽量使得种种岗位上的要素数量只有贰个,那么当大家用 hash 算法求得这几个岗位的时候,登时就足以掌握对应地方的因素正是大家要的,而不用再去遍历链表,那样就大大优化了询问的功能。

对于随便给定的靶子,只要它的 hashCode() 重临值同样,那么程序调用 hash(int h) 方法所总括获得的 hash 码值总是同样的。我们率先想到的便是把 hash 值对数高管度取模运算,这样壹来,成分的遍布相对来讲是比较均匀的。但是,“模”运算的损耗照旧一点都十分的大的,在 HashMap 中是这么做的:调用 indexFor(int h, int length) 方法来计量该对象应该保留在 table 数组的哪些索引处。indexFor(int h, int length) 方法的代码如下:

/**
     * Returns index for hash code h.
     */
static int indexFor(int h, int length) {  
    return h & (length-1);
}

其壹办法拾分奇妙,它通过 h & (table.length -一) 来获得该指标的保存位,而 HashMap 底层数组的长短总是 贰 的 n 次方,那是 HashMap 在进程上的优化。在 HashMap 构造器中有如下代码:

// Find a power of 2 >= initialCapacity
int capacity = 1;
    while (capacity < initialCapacity)  
        capacity <<= 1;

这段代码保证开头化时 HashMap 的体量总是 二 的 n 次方,即底层数组的长度总是为 二 的 n 次方。

当 length 总是 二 的 n 次方时,h& (length-壹)运算等价于对 length 取模,也正是 h%length,可是 & 比 % 具有更加高的频率。那看起来很简短,其实正如有玄机的,大家譬如来注明:

借使数CEO度分别为 壹伍 和 1陆,优化后的 hash 码分别为 捌 和 九,那么 & 运算后的结果如下:

h & (table.length-1) hash table.length-1
8 & (15-1): 0100 & 1110 = 0100
9 & (15-1): 0101 & 1110 = 0100
8 & (16-1): 0100 & 1111 = 0100
9 & (16-1): 0101 & 1111 = 0101
从地点的例子中得以见到:当它们和 1五-一(11十)“与”的时候,发生了相同的结果,也正是说它们会固定到数组中的同三个岗位上去,这就发出了磕碰,8和 玖会被内置数组中的同二个任务上变成链表,那么查询的时候就要求遍历那个链 表,获得八或然玖,那样就降低了查询的频率。同不平日间,大家也足以窥见,当数主任度为 1五 的时候,hash 值会与 壹伍-1(1110)进行“与”,那么最终一个人永久是 0,而 000一,001一,0十一,100一,拾1一,011一,1十一这多少个岗位永恒都不可能存放元素了,空间浪费非常的大,更糟的是这种情景中,数组能够运用的职位比数老董度小了众多,那代表进一步增多了磕碰的概率,减慢了查询的频率!而当数老板度为16时,即为二的n次方时,二n-一得到的贰进制数的各样位上的值都为 一,那使得在低位上&时,获得的和原 hash 的未有同样,加之 hash(int h)方法对 key 的 hashCode 的愈加优化,参预了高位总计,就使得只有同样的 hash 值的八个值才会被停放数组中的同多个地方上变成链表。

因此说,当数首席营业官度为 二 的 n 次幂的时候,不相同的 key 算得得 index 一样的概率非常小,那么数量在数组上布满就比较均匀,也正是说碰撞的概率小,相对的,查询的时候就无须遍历某些地点上的链表,那样查询作用也就较高了。

基于上边 put 方法的源代码能够观望,当程序试图将壹个key-value对放入HashMap中时,程序首先依照该 key 的 hashCode() 重回值决定该 Entry 的积攒地点:假使七个 Entry 的 key 的 hashCode() 重临值同样,那它们的仓库储存地方同样。如若那三个 Entry 的 key 通过 equals 相比再次回到 true,新扩大加 Entry 的 value 将掩盖集结中原本 Entry 的 value,但key不会覆盖。如若那三个 Entry 的 key 通过 equals 比较再次来到false,新扩展长的 Entry 将与聚集中原始 Entry 产生 Entry 链,而且新添长的 Entry 位于 Entry 链的头顶——具体表明继续看 addEntry() 方法的证实。

get方法

get方法由getNode方法完毕:

  • 要是在数组下标的链表头就找到key一样的,那么重回链表头的值
  • 再不1经数组下标处的项目是TreeNode,就在红黑树中搜索
  • 不然正是在平常链表中查找了
  • 都找不到就再次回到null

remove方法的流程大约和get方法类似。

HashMap的扩容,resize()过程?

newCap = oldCap << 1

resize方法中有这样一句,表达是扩大容积后数组大小是原数组的两倍。

Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
        table = newTab;
        if (oldTab != null) {
            for (int j = 0; j < oldCap;   j) {
                Node<K,V> e;
                if ((e = oldTab[j]) != null) {
                    oldTab[j] = null;
                    // 如果数组中只有一个元素,即只有一个头结点,重新哈希到新数组的某个下标
                    if (e.next == null)
                        newTab[e.hash & (newCap - 1)] = e;
                    else if (e instanceof TreeNode)
                        ((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
                    else { // preserve order
                        // 数组下标处的链表长度大于1,非红黑树的情况
                        Node<K,V> loHead = null, loTail = null;
                        Node<K,V> hiHead = null, hiTail = null;
                        Node<K,V> next;
                        do {
                            next = e.next;
                            // oldCap是2的次幂,最高位是1,其余为是0,哈希值和其相与,根据哈希值的最高位是1还是0,链表被拆分成两条,哈希值最高位是0分到loHead。
                            if ((e.hash & oldCap) == 0) {
                                if (loTail == null)
                                    loHead = e;
                                else
                                    loTail.next = e;
                                loTail = e;
                            }
                            // 哈希值最高位是1分到hiHead
                            else {
                                if (hiTail == null)
                                    hiHead = e;
                                else
                                    hiTail.next = e;
                                hiTail = e;
                            }
                        } while ((e = next) != null);
                        if (loTail != null) {
                            loTail.next = null;
                            // loHead挂到新数组[原下标]处;
                            newTab[j] = loHead;
                        }
                        if (hiTail != null) {
                            hiTail.next = null;
                            // hiHead挂到,新数组中[原下标 oldCap]处
                            newTab[j   oldCap] = hiHead;
                        }
                    }
                }
            }
        }
        return newTab;

比方,比如oldCap是1陆,2进制表示是一千0,hash值的后五人和oldCap相与,因为oldCap的最高位(从右往左数的第九位)是一别的位是0,因而hash值的该位是0的具备因素被分到一条链表,挂到新数组中原下标处,hash值该位为一的被分到此外一条链表,挂到新数组中原下标 oldCap处。比方:桶0中的成分其hash值后5位是0XXXX的就被分到桶0种,其hash值后八位是一XXXX就被分到桶四中。


by @sunhaiyu

2018.7.26

搜索操作同理,先通过哈希函数计算出实际存款和储蓄位置,然后从数组中对应地址抽取就可以。

读取
/**
     * Returns the value to which the specified key is mapped,
     * or {@code null} if this map contains no mapping for the key.
     *
     * <p>More formally, if this map contains a mapping from a key
     * {@code k} to a value {@code v} such that {@code (key==null ? k==null :
     * key.equals(k))}, then this method returns {@code v}; otherwise
     * it returns {@code null}.  (There can be at most one such mapping.)
     *
     * <p>A return value of {@code null} does not <i>necessarily</i>
     * indicate that the map contains no mapping for the key; it's also
     * possible that the map explicitly maps the key to {@code null}.
     * The {@link #containsKey containsKey} operation may be used to
     * distinguish these two cases.
     *
     * @see #put(Object, Object)
     */
    public V get(Object key) {
        if (key == null)
            return getForNullKey();
        Entry<K,V> entry = getEntry(key);

        return null == entry ? null : entry.getValue();
    }
    final Entry<K,V> getEntry(Object key) {
        int hash = (key == null) ? 0 : hash(key);
        for (Entry<K,V> e = table[indexFor(hash, table.length)];
             e != null;
             e = e.next) {
            Object k;
            if (e.hash == hash &&
                ((k = e.key) == key || (key != null && key.equals(k))))
                return e;
        }
        return null;
    }

有了地点存款和储蓄时的 hash 算法作为基础,明白起来这段代码就很轻松了。从地点的源代码中得以见见:从 HashMap 中 get 成分时,首先总括 key 的 hashCode,找到数组中对应地方的某壹成分,然后经过 key 的 equals 方法在对应地方的链表中找到供给的要素。

xpj手机娱乐中心 3

归纳

简单易行地说,HashMap 在底层将 key-value 当成1个完完全全进行拍卖,这一个共同体便是多少个 Entry 对象。HashMap 底层采取贰个Entry[] 数组来保存全数的 key-value 对,当须求仓库储存贰个 Entry 对象时,会根据 hash 算法来支配其在数组中的存款和储蓄地点,在依据 equals 方法决定其在该数组地方上的链表中的存款和储蓄地方;当必要抽出3个Entry 时,也会依照 hash 算法找到其在数组中的存款和储蓄地点,再依靠 equals 方法从该职分上的链表中收取该Entry。

从上海教室大家能够窥见哈希表是由数组 链表组成的,假如四个尺寸为16的数组(暗许大小)中,每一种成分存款和储蓄的是两个链表的头结点。一般景观是经过类似取模的法子获得(实际使用indexFor(int h, int length)方法和取模的结果一律,但功效越来越高)。这里大家先即使使用取模的主意则上述哈希表中:
12=12,28=12,108=12,140=12。
之所以12、28、10八以及140都存款和储蓄在数组下标为1二的岗位。

HashMap 的 resize(rehash)

当 HashMap 中的成分尤为多的时候,hash 争辩的可能率也就越来越高,因为数组的尺寸是定点的。所以为了增加查询的成效,将在对 HashMap 的数组进行扩大容积,数组扩大容积那么些操作也会冒出在 ArrayList 中,那是三个常用的操作,而在 HashMap 数组扩大容积之后,最消耗质量的点就出现了:原数组中的数据必须重新计算其在新数组中的地点,并放进去,那正是resize。

那正是说 HashMap 何时实行扩大体量呢?当 HashMap 中的成分个数超过数组大小 loadFactor时,就能够议及展览开数组扩大容积,loadFactor的暗许值为 0.7伍,那是三个折中的取值。约等于说,暗中认可景况下,数组大小为 1陆,那么当 HashMap 瓜时素个数超越 160.75=1二 的时候,就把数组的大小增加为 二*16=3二,即扩充壹倍,然后重新总结各个成分在数组中的地点,而那是一个要命消耗质量的操作,所以借使大家已经预言HashMap 七月素的个数,那么预设成分的个数能够使得的增高 HashMap 的性质。

本文由澳门新葡亰发布于计算机知识,转载请注明出处:HashMap的实现原理,的实现原理

关键词: 葡京国际娱乐 其他 JAVA-集合

最火资讯