前沿拓展:java整形多少位

看一下 美鏈網(wǎng) 上面的介紹,煙針馬吸度引們藥逐來量還是多比較再選擇比較好希望能給您提供幫助,可以給個(gè)大大的贊不。

前言

閱讀前請(qǐng)先看看如下幾個(gè)問題,如果有不清楚的地方看完本文會(huì)有收獲

HashMap(int initialCapacity)

在JDK的HashMap中存在無參構(gòu)造函數(shù)和有參構(gòu)造函數(shù),有參構(gòu)造函數(shù)中又存在帶有指定容量和加載因子的構(gòu)造方法和只帶有指定容量的構(gòu)造方法,分析下 HashMap(int initialCapacity) 構(gòu)造方法

public HashMap(int initialCapacity) { this(initialCapacity, DEFAULT_LOAD_FACTOR); } 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); }

該方法邏輯比較簡(jiǎn)單首先校驗(yàn)下容量有沒有超多大值,沒有的話設(shè)置下加載

算法分析

生成擴(kuò)容閾值的算法如下,該算法的巧妙的用位運(yùn)算生成大于等于指定容量的小的2的冪次值例如如果給定一個(gè)數(shù)為14那么算出大于14的2的小指數(shù)冪等于16

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; }

在十進(jìn)制數(shù)中2的整數(shù)次冪對(duì)應(yīng)的二進(jìn)制數(shù)有效位為1且有效位后所有位為0,如下圖所示

tableSizeFor方法為什么先做cap-1操作?當(dāng)cap已經(jīng)為2的整數(shù)次冪時(shí)通過該方法計(jì)算會(huì)將原來的cap變?yōu)?*cap,其實(shí)就是為了處理特殊的數(shù)據(jù)為什么每次無符號(hào)移位操作是1,2,4,8,16?在java中int類型為32位,1+2+4+8+16正好是移動(dòng)32位,移動(dòng)32位后的得到的結(jié)果是將高有效位及以后所有位變0位1

假設(shè)cap=14,cap-1 =13 其二進(jìn)制位1101經(jīng)過下圖的變化后發(fā)現(xiàn)在第一次位運(yùn)算后所有有效位都為1111,因此在剩下的四次位運(yùn)算后終結(jié)果就是1111,后將1111+1=10000得到十進(jìn)制數(shù)位16。

構(gòu)造方法雖然設(shè)置了hashmap的threshold但是并沒有真正設(shè)置hashmap的容量大小,真正容量大小是在向hashmap中插入第一個(gè)元素時(shí)進(jìn)行設(shè)置

HashMap 內(nèi)存分配時(shí)機(jī)

經(jīng)過構(gòu)造函數(shù)new的Hashmap對(duì)象并未真正分配內(nèi)存空間,這其實(shí)是一種優(yōu)化因?yàn)樵跇?gòu)造方法就分配內(nèi)存空間后很久才進(jìn)行插入操作那么這部分內(nèi)存其實(shí)是浪費(fèi)的。因此在put操作時(shí)會(huì)進(jìn)行判斷如果第一次插入則通過resize方法進(jìn)行進(jìn)行分配空間。第一次插入時(shí)分配的空間大小即為tablesizefor方法返回大小

這種分配方式滿足程序局部性原理,在寫代碼時(shí)可以借鑒

put方法插入數(shù)據(jù)前判斷當(dāng)前hashMap中table是否初始化未初始化進(jìn)行resize操作,其實(shí)hashmap的初始內(nèi)存分配跟擴(kuò)容都是通過resize方法來完成resize方法內(nèi)部通過各種參數(shù)判斷來執(zhí)行初始化邏輯跟擴(kuò)容邏輯內(nèi)存分配邏輯-resize

本文只截取部分resize方法分析,剩余擴(kuò)容邏輯會(huì)在新文章中進(jìn)行講解。

首先判斷table 是否為空,因?yàn)槌跏蓟A段table=null所以oldCap=0由于在hashmap中帶參數(shù)的構(gòu)造方法通過tableSizeFor方法設(shè)置了threshold因此table數(shù)據(jù)的容量為oldThr如果使用無參數(shù)構(gòu)造方法newCap&newThr均使用默認(rèn)值后創(chuàng)建數(shù)據(jù)并指向table

總結(jié)new hashmap(cap)初始大小為tableSizeFor大小空間分配是在插入時(shí)分配由于tableSizeFor是2的整數(shù)冪所以與0.75相乘結(jié)果為整數(shù)

HashMap使用巧妙且的算法獲取了大于等于給定容量的小2的整數(shù)冪,所以在根據(jù)hashcode計(jì)算元素所屬hash表的位置時(shí)通過hashcode與(hash表長(zhǎng)度-1)進(jìn)行取模快速定位。在插入進(jìn)行內(nèi)存分配機(jī)制極大的避免了內(nèi)存浪費(fèi)而且滿足了局部性原理同樣值得學(xué)習(xí)

拓展知識(shí):java整形多少位

還有其他疑惑?想了解更多?可以點(diǎn)擊 【在線咨詢】