国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Java HashMap初始化大小設(shè)置多少合適

這篇具有很好參考價(jià)值的文章主要介紹了Java HashMap初始化大小設(shè)置多少合適。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

修改公司老代碼的時(shí)候,發(fā)現(xiàn)阿里編碼規(guī)約插件提示HashMap初始化時(shí)盡量指定初始值大小,因?yàn)樵O(shè)置合理的初始值可以提升性能:

map設(shè)置初始容量,Java知識(shí),java,HashMap,初始值

?HashMap繼承自AbstractMap類,實(shí)現(xiàn)了Map、Cloneable、java.io.Serializable接口,是基于散列表實(shí)現(xiàn)的雙列集合,它存儲(chǔ)的是key-value鍵值對(duì)映射,每個(gè)key-value鍵值對(duì)也被稱為一條Entry條目。其中的 key與 value,可以是任意的數(shù)據(jù)類型,其類型可以相同也可以不同。但一般情況下,key都是String類型,有時(shí)候也可以使用Integer類型;value可以是任何類型。并且在HashMap中,最多只能有一個(gè)記錄的key為null,但可以有多個(gè)value的值為null。HashMap中這些鍵值對(duì)(Entry)會(huì)分散存儲(chǔ)在一個(gè)數(shù)組當(dāng)中,這個(gè)數(shù)組就是HashMap的主體。

HashMap的實(shí)例有兩個(gè)影響其性能的參數(shù):初始容量和裝載因子。容量是哈希表中的桶數(shù),初始容量就是創(chuàng)建哈希表時(shí)的容量。負(fù)載因子是一種度量方法,用來衡量在自動(dòng)增加哈希表的容量之前,哈希表允許達(dá)到的滿度。當(dāng)哈希表中的條目數(shù)超過負(fù)載因子和當(dāng)前容量的乘積時(shí),哈希表將被重新哈希(即重新構(gòu)建內(nèi)部數(shù)據(jù)結(jié)構(gòu)),這樣哈希表的桶數(shù)大約是原來的兩倍。

那么在使用HashMap時(shí)要求盡量指定初始值,該指定多少合適?(可以直接跳到后面看結(jié)論)

一般來說,初始值大小的設(shè)定應(yīng)該根據(jù)實(shí)際需要進(jìn)行設(shè)置。另外,也建議將初始值大小設(shè)置為2的冪次方,這樣可以更好地利用HashMap的內(nèi)部機(jī)制,提高程序的運(yùn)行效率。

如果不設(shè)置,默認(rèn)值是16。

如我截圖的代碼,就存放2個(gè)變量,初始值設(shè)置2,但是設(shè)置2真的合理嗎?

我們可以看一下HashMap的源碼,看看它里面是怎么實(shí)現(xiàn)的。

不設(shè)置初始值的構(gòu)造方法:

/**
 * Constructs an empty <tt>HashMap</tt> with the default initial capacity
 * (16) and the default load factor (0.75).
 */
public HashMap() {
    this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}

設(shè)置初始值的構(gòu)造方法:

/**
 * Constructs an empty <tt>HashMap</tt> with the specified initial
 * capacity and the default load factor (0.75).
 *
 * @param  initialCapacity the initial capacity.
 * @throws IllegalArgumentException if the initial capacity is negative.
 */
public HashMap(int initialCapacity) {
    this(initialCapacity, DEFAULT_LOAD_FACTOR);
}

this方法的源碼:

/**
 * Constructs an empty <tt>HashMap</tt> with the specified initial
 * capacity and load factor.
 *
 * @param  initialCapacity the initial capacity
 * @param  loadFactor      the load factor
 * @throws IllegalArgumentException if the initial capacity is negative
 *         or the load factor is nonpositive
 */
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);
    this.loadFactor = loadFactor;
    this.threshold = tableSizeFor(initialCapacity);
}

里面的變量和方法,,我加了一些翻譯說明:

/**
 * The next size value at which to resize (capacity * load factor).
 * 翻譯:用于調(diào)整大小的下一次大小值(容量*負(fù)載因子)
 * @serial
 */
// (The javadoc description is true upon serialization.
// Additionally, if the table array has not been allocated, this
// field holds the initial array capacity, or zero signifying
// DEFAULT_INITIAL_CAPACITY.)
int threshold;

//默認(rèn)大小為16
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16


/**
     * Returns a power of two size for the given target capacity.(翻譯:返回給定目標(biāo)容量的大小為2的冪)
     * 這段代碼是一個(gè)名為 tableSizeFor 的靜態(tài)方法,它接受一個(gè)整數(shù)參數(shù) cap,并返回一個(gè)整數(shù)值。該方法的作用是計(jì)算并返回一個(gè)用于散列表(hash table)的合適的大小。
     *
     * 具體來說,該方法首先將 cap 減去 1,然后使用位運(yùn)算符將結(jié)果向右移動(dòng),并按位或運(yùn)算,以清除最低位的 1。
     * 這個(gè)過程會(huì)重復(fù) 5 次,每次向右移動(dòng)的位數(shù)為 1、2、4、8 和 16。最后,如果計(jì)算出的值小于 0,則返回 1;
     * 如果計(jì)算出的值大于等于 MAXIMUM_CAPACITY,則返回 MAXIMUM_CAPACITY;否則返回計(jì)算出的值加 1。
     *
     * 這個(gè)方法的設(shè)計(jì)目的是為了在散列表中獲得更好的負(fù)載因子(load factor),從而減少哈希沖突(hash collision)的概率。
     * 負(fù)載因子是指散列表中元素的數(shù)量與散列表大小的比率。較小的負(fù)載因子意味著每個(gè)桶(bucket)中存儲(chǔ)的元素較少,從而減少了哈希沖突的概率。
     * 但是,較小的負(fù)載因子也會(huì)導(dǎo)致散列表的空間利用率較低。因此,選擇合適的散列表大小非常重要。
     * @param cap
     * @return
     */
    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;
    }

上面的源碼可以看出threshold是個(gè)閾值,它的計(jì)算是根據(jù)tableSizeFor方法來的(根據(jù)設(shè)置的初始值計(jì)算的),到達(dá)這個(gè)閾值就會(huì)觸發(fā)擴(kuò)容,擴(kuò)容是會(huì)影響性能的。

再看一下putMapEntries方法的源碼,看注釋的意思是實(shí)現(xiàn)了Map.putAll和Map構(gòu)造函數(shù):

/**
 * Implements Map.putAll and Map constructor.
 *
 * @param m the map
 * @param evict false when initially constructing this map, else
 * true (relayed to method afterNodeInsertion).
 */
final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {
    int s = m.size();
    if (s > 0) {
        if (table == null) { // pre-size
            float ft = ((float)s / loadFactor) + 1.0F;
            int t = ((ft < (float)MAXIMUM_CAPACITY) ?
                     (int)ft : MAXIMUM_CAPACITY);
            if (t > threshold)
                threshold = tableSizeFor(t);
        }
        else if (s > threshold)
            resize();
        for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
            K key = e.getKey();
            V value = e.getValue();
            putVal(hash(key), key, value, false, evict);
        }
    }
}

這里面“?float ft = ((float)s / loadFactor) + 1.0F;”就是我們初始值的大小計(jì)算方法。

有興趣的可以看下HashMap源碼研究一下。

結(jié)論:默認(rèn)不設(shè)置初始值大小,HashMap使用的是默認(rèn)大小,值為16,如果要指定大小可以根據(jù)“存儲(chǔ)數(shù)據(jù)的個(gè)數(shù)/0.75+1”計(jì)算出的結(jié)果作為初始值。

最后說明一下上面我的截圖代碼的問題,設(shè)置2是否合理?答案是不合理,根據(jù)計(jì)算公式得出,設(shè)置3是比較合理的。

原因是設(shè)置為2,剛好會(huì)觸發(fā)擴(kuò)容,造成完全沒有必要的性能浪費(fèi)。

參考以下代碼,設(shè)置為2:

Map<String, String> map = new HashMap<>(2);
map.put("startTime", "");
getMapLength(map);
map.put("endTime", "");
getMapLength(map);

結(jié)果為:說明進(jìn)行了擴(kuò)容

map設(shè)置初始容量,Java知識(shí),java,HashMap,初始值

設(shè)置為3:

Map<String, String> map = new HashMap<>(3);
map.put("startTime", "");
getMapLength(map);
map.put("endTime", "");
getMapLength(map);

結(jié)果為:沒有進(jìn)行擴(kuò)容

map設(shè)置初始容量,Java知識(shí),java,HashMap,初始值

打印Length方法:

/**
     * 打印Length
     * @param map
     * @throws Exception
     */
    static void getMapLength(Map<String, String> map) throws Exception {
        Field field = HashMap.class.getDeclaredField("table");
        field.setAccessible(true);
        Object[] elementData = (Object[]) field.get(map);
        System.out.println(elementData == null ? 0 : elementData.length);
    }

PS:關(guān)于是否設(shè)置初始值影響性能、初始值設(shè)置的合理與否影響性能,可以通過測(cè)試代碼測(cè)一下,看看初始化的時(shí)間間隔。文章來源地址http://www.zghlxwxcb.cn/news/detail-704131.html

到了這里,關(guān)于Java HashMap初始化大小設(shè)置多少合適的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Git設(shè)置初始化默認(rèn)分支為main

    github創(chuàng)建項(xiàng)目的默認(rèn)分支為main。本地創(chuàng)建的git分支默認(rèn)為master,每次在本地新建一個(gè)倉庫再關(guān)聯(lián)到remote,分支不統(tǒng)一。 git在2.28版本中提供了一個(gè)配置,指定在執(zhí)行 git init 的時(shí)候生成的默認(rèn)分支 本地git版本不夠的話先升級(jí); 如果使用homebrew安裝的git,直接升級(jí)即可 或者可以

    2024年02月13日
    瀏覽(16)
  • 5、Citrix云桌面初始化Storefront設(shè)置

    目錄 一、前言 二、初始過程 三、總結(jié)? 當(dāng)我們使用云桌面時(shí)候,不小心損壞Citrix Storefront,可以通過初始化進(jìn)行重置。 1、 確保 StoreFront 管理控制臺(tái)已關(guān)閉;

    2024年02月16日
    瀏覽(21)
  • STM32 GPIO設(shè)置(GPIO初始化)學(xué)習(xí)筆記

    STM32 GPIO設(shè)置(GPIO初始化)學(xué)習(xí)筆記

    GPIO 都知道是 通用輸入輸出接口 的意思就不詳細(xì)解釋 那么我們就直接進(jìn)入怎么設(shè)置GPIO接口: 這里我的編譯軟件是keil5,相信大家都應(yīng)該知道stm32有各種的工作模式上拉、下拉、推挽、開漏等等。如果想要了解具體的工作模式原理這里我推薦大家看:推挽 開漏 高阻 這都是誰

    2024年03月28日
    瀏覽(29)
  • Java的初始化塊

    三種初始化數(shù)據(jù)域的方法: 在構(gòu)造器中設(shè)置值 在聲明中賦值 初始化塊(initialization block) 在一個(gè)類的聲明中,可以包含多個(gè)代碼塊。只要構(gòu)造類的對(duì)象,這些塊就會(huì)被執(zhí)行。 在上面這個(gè)示例中,無論使用哪個(gè)構(gòu)造器構(gòu)造對(duì)象,id 域都在對(duì)象初始化塊中被初始化。首先運(yùn)行初

    2023年04月27日
    瀏覽(28)
  • pygame學(xué)習(xí)(一)——pygame庫的導(dǎo)包、初始化、窗口的設(shè)置、打印文字

    pygame學(xué)習(xí)(一)——pygame庫的導(dǎo)包、初始化、窗口的設(shè)置、打印文字

    pygame是一個(gè)跨平臺(tái)Python庫(pygame news),專門用來開發(fā)游戲。pygame主要為開發(fā)、設(shè)計(jì)2D電子游戲而生,提供圖像模塊(image)、聲音模塊(mixer)、輸入/輸出(鼠標(biāo)、鍵盤、顯示屏)模塊等。使用pygame,理論上可以開發(fā)設(shè)計(jì)市面上所有的2D類型游戲。 優(yōu)點(diǎn):pygame免費(fèi)、開源,支持

    2024年02月03日
    瀏覽(32)
  • Java之初始化順序?qū)嵺`

    在創(chuàng)建Java對(duì)象時(shí),需要將對(duì)象中的成員變量進(jìn)行初始化后,才能調(diào)用對(duì)象的構(gòu)造方法創(chuàng)建對(duì)象。本文中將會(huì)講解初始化時(shí)父類與子類對(duì)應(yīng)的順序。 場(chǎng)景1:父類、子類的初始化順序 用例代碼 結(jié)果輸出 結(jié)果分析 先初始化靜態(tài)塊:父類的靜態(tài)塊 - 子類的靜態(tài)塊。 再初始化非靜

    2024年02月11日
    瀏覽(23)
  • java中初始化數(shù)組的方法

    方式一: 注:此種方式創(chuàng)建的數(shù)組,如不顯式初始化數(shù)組元素,則各元素為當(dāng)前數(shù)據(jù)類型的默認(rèn)值?;緮?shù)據(jù)類型為0,對(duì)象類型為null。所以使用前需要將各元素顯式賦值。 方式二: 注:此方式與方式一的結(jié)果相同,但是更簡便。 方式三: 注:此方式與方式一和方式二的結(jié)

    2024年02月12日
    瀏覽(24)
  • Java集合類型對(duì)象的快速初始化

    在Java中, 集合類型的對(duì)象初始化, 一般是先創(chuàng)建對(duì)象, 然后往集合里面增加元素,這種寫法直觀,但是撰寫代碼的時(shí)候感覺比較冗余, 是否有什么酷炫的方式簡化定義初始化呢? 本篇介紹字符串?dāng)?shù)組、List 和 Map類型對(duì)象的定義初始化簡單方式。 常用的寫法: 簡化的寫法

    2024年02月06日
    瀏覽(40)
  • Java中Map集合初始化并賦值

    Java中Map集合初始化并賦值的幾種方式:

    2024年02月11日
    瀏覽(20)
  • 【Java】構(gòu)造方法及類的初始化

    【Java】構(gòu)造方法及類的初始化

    活動(dòng)地址:CSDN21天學(xué)習(xí)挑戰(zhàn)賽 ? 博客主頁: XIN-XIANG榮 ? 系列專欄: 【Java SE】 ? 一句短話: 難在堅(jiān)持,貴在堅(jiān)持,成在堅(jiān)持! 構(gòu)造方法(也稱為構(gòu)造器)是一個(gè)特殊的成員方法,其名字必須與類名相同,在創(chuàng)建對(duì)象時(shí),由編譯器自動(dòng)調(diào)用,并且在整個(gè)對(duì)象的生命周期內(nèi)只調(diào)用一次。

    2023年04月10日
    瀏覽(17)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包