摘要:估計(jì)這就是推薦使用的主要原因吧正負(fù)標(biāo)識(shí)判斷輸入的字符串是否為開頭轉(zhuǎn)化邏輯字符串轉(zhuǎn)化為的關(guān)鍵在于數(shù)組,以進(jìn)制為例,用表示到,滿才會(huì)進(jìn)。
Integer的基本實(shí)現(xiàn)Integer的基本實(shí)現(xiàn)
Integer的使用
Integer封裝的操作
基本描述:
Integer是對(duì)原生基本類型int的封裝,其定義value來存儲(chǔ)值和一些用于描述int的信息
int value;//int int SIZE = 32;//1位正負(fù)標(biāo)識(shí)+31位數(shù)據(jù) int BYTES = SIZE / Byte.SIZE;//所占字節(jié) int MIN_VALUE = 0x80000000;//最小值,32個(gè)1 int MAX_VALUE = 0x7fffffff;//最大值,0+31個(gè)1
構(gòu)造函數(shù):
允許通過String和int入?yún)頌関alue賦值,但是兩個(gè)構(gòu)造函數(shù)都已棄用
通過注釋可以看到,推薦通過valueOf()的方法來返回一個(gè)Integer
/** * @deprecated * It is rarely appropriate to use this constructor. The static factory * {@link #valueOf(int)} is generally a better choice, as it is * likely to yield significantly better space and time performance. */ @Deprecated(since="9") public Integer(int value) { this.value = value; } /** * @deprecated * It is rarely appropriate to use this constructor. * Use {@link #parseInt(String)} to convert a string to a * {@code int} primitive, or use {@link #valueOf(String)} * to convert a string to an {@code Integer} object. */ @Deprecated(since="9") public Integer(String s) throws NumberFormatException { this.value = parseInt(s, 10); }
使用推薦的方法獲取Integer實(shí)例和構(gòu)造方法有何不同?
//----------------------int入?yún)?----------------- @HotSpotIntrinsicCandidate public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); } //----------------------String入?yún)?----------------- public static Integer valueOf(String s) throws NumberFormatException { return Integer.valueOf(parseInt(s, 10)); } //radix表示進(jìn)制,取值范圍為[2, 36] public static Integer valueOf(String s, int radix) throws NumberFormatException { return Integer.valueOf(parseInt(s,radix)); }
int入?yún)?/p>
如果入?yún)⒅械膇nt在IntegerCache內(nèi)部類的Integer cache[]中存在則返回?cái)?shù)組中的Integer否則通過構(gòu)造函數(shù)創(chuàng)建(棄用的那個(gè))
String入?yún)?/p>
通過parseInt(s,radix)方法解析字符串,返回int值
radix參數(shù)表示字符串轉(zhuǎn)換的int值的進(jìn)制,其取值范圍為[2,36]
解析IntegerCache和parseInt的實(shí)現(xiàn)
IntegerCache
//The cache is initialized on first usage. private static class IntegerCache { static final int low = -128; static final int high; static final Integer cache[]; static { // high value may be configured by property int h = 127; //The size of the cache may be controlled by the {@code -XX:AutoBoxCacheMax=} option. String integerCacheHighPropValue = VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { try { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } catch( NumberFormatException nfe) { // If the property cannot be parsed into an int, ignore it. } } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); // range [-128, 127] must be interned (JLS7 5.1.7) assert IntegerCache.high >= 127; } private IntegerCache() {} }
IntegerCache是一個(gè)私有靜態(tài)內(nèi)部類該類內(nèi)部定義了一個(gè)數(shù)組Integer cache[],數(shù)組內(nèi)的數(shù)據(jù)由-128起始,默認(rèn)至127為止(byte的范圍)
該數(shù)組的最大值可通過在jvm中設(shè)置
-XX:AutoBoxCacheMax=
數(shù)組cache[128]為0,valueof(int)參數(shù)的值符合這個(gè)范圍都會(huì)直接從數(shù)組中返回Integer
有意思的是valueof(int)是@HotSpotIntrinsicCandidate的,關(guān)于它的描述是這樣的:
JDK的源碼中,被@HotSpotIntrinsicCandidate標(biāo)注的方法,在HotSpot中都有一套高效的實(shí)現(xiàn),該高效實(shí)現(xiàn)基于CPU指令,運(yùn)行時(shí),HotSpot維護(hù)的高效實(shí)現(xiàn)會(huì)替代JDK的源碼實(shí)現(xiàn),從而獲得更高的效率。
估計(jì)這就是推薦使用的主要原因吧!
parseInt
public static int parseInt(String s, int radix) throws NumberFormatException { ... boolean negative = false;//正負(fù)標(biāo)識(shí) int i = 0, len = s.length(); int limit = -Integer.MAX_VALUE; if (len > 0) { char firstChar = s.charAt(0); //判斷輸入的字符串是否為"-"開頭 if (firstChar < "0") { // Possible leading "+" or "-" if (firstChar == "-") { negative = true; limit = Integer.MIN_VALUE; } else if (firstChar != "+") { throw NumberFormatException.forInputString(s); } if (len == 1) { // Cannot have lone "+" or "-" throw NumberFormatException.forInputString(s); } i++; } //轉(zhuǎn)化邏輯 int multmin = limit / radix; int result = 0; while (i < len) { // Accumulating negatively avoids surprises near MAX_VALUE int digit = Character.digit(s.charAt(i++), radix); if (digit < 0 || result < multmin) { throw NumberFormatException.forInputString(s); } result *= radix; if (result < limit + digit) { throw NumberFormatException.forInputString(s); } result -= digit; } return negative ? result : -result; } else { throw NumberFormatException.forInputString(s); } } static final char[] digits = { "0" , "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" , "a" , "b" , "c" , "d" , "e" , "f" , "g" , "h" , "i" , "j" , "k" , "l" , "m" , "n" , "o" , "p" , "q" , "r" , "s" , "t" , "u" , "v" , "w" , "x" , "y" , "z" };
字符串轉(zhuǎn)化為int的關(guān)鍵在于digits數(shù)組,以16進(jìn)制為例,用0...9,a...f表示0到15,滿16才會(huì)進(jìn)1。也就是超過10進(jìn)制以后,大于10的數(shù)要使用a開始的字母表示,但是字母只有26個(gè),進(jìn)制又必須從2開始,故進(jìn)制的取值范圍也就定義為[2, 36]
故入?yún)⒌淖址畇也必須符合digits數(shù)組中的元素以及額外的只可能存在第一位"+"或者"-"
parseInt的轉(zhuǎn)化邏輯為:
在每次循環(huán)中
取出digit,確定進(jìn)制后轉(zhuǎn)化的int數(shù)
通過result *= radix;把上一次循環(huán)的數(shù)據(jù)進(jìn)一位
通過result -= digit;把當(dāng)前的數(shù)據(jù)加入result
然后返回結(jié)果,通過:
return negative ? result : -result;
int a = 5; Integer w = 6; Integer test = Integer.valueOf(w); int testP = Integer.valueOf(a);
轉(zhuǎn)化成對(duì)應(yīng)的字節(jié)碼,則
int a = 5
0: iconst_5
1: istore_1
直接將自然數(shù)壓棧
Integer w = 6
2: bipush 6
4: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
7: astore_2
調(diào)用Integer的靜態(tài)方法valueof(6)得到Integer實(shí)例
Integer test = Integer.valueOf(w)
8: aload_2
9: invokevirtual #3 // Method java/lang/Integer.intValue:()I
12: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
15: astore_3
獲取操作數(shù)棧中w的引用,調(diào)用intValue返回int值,再通過valueof獲取Integer實(shí)例
int testP = Integer.valueOf(a)
16: iload_1
17: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
20: invokevirtual #3 // Method java/lang/Integer.intValue:()I
獲取操作數(shù)棧中的a,調(diào)用valueof獲取Integer實(shí)例,再通過intValue返回int值
由此可知,對(duì)于基本類型的封裝類,編譯器會(huì)自動(dòng)調(diào)用其一些方法來實(shí)現(xiàn)用戶操作的簡(jiǎn)化!
Integer封裝的操作Object虛函數(shù)的實(shí)現(xiàn)
父類Number的虛函數(shù)實(shí)現(xiàn)
字節(jié)操作
Object虛函數(shù)的實(shí)現(xiàn)
public boolean equals(Object obj) { if (obj instanceof Integer) { return value == ((Integer)obj).intValue(); } return false; } public static int hashCode(int value) { return value; } public static String toString(int i) { int size = stringSize(i); if (COMPACT_STRINGS) { byte[] buf = new byte[size]; getChars(i, size, buf); return new String(buf, LATIN1); } else { byte[] buf = new byte[size * 2]; StringUTF16.getChars(i, size, buf); return new String(buf, UTF16); } }
equals
通過Integer的intValue獲取入?yún)⒌腎nteger封裝的int值并與value進(jìn)行==尋址判斷
hashCode
hashCode返回的就是一個(gè)int值,故直接使用value本身
toString
使用char數(shù)組做中轉(zhuǎn),通過String實(shí)例化一個(gè)String實(shí)例
根據(jù)是否開啟壓縮機(jī)制判斷使用的是LATIN1還是UTF16
父類Number的虛函數(shù)實(shí)現(xiàn)
public byte byteValue() { return (byte)value; } public double doubleValue() { return (double)value; } public float floatValue() { return (float)value; } public int intValue() { return value; } public long longValue() { return (long)value; } public short shortValue() { return (short)value; }
只是對(duì)value進(jìn)行強(qiáng)轉(zhuǎn)
字節(jié)操作
計(jì)算int二進(jìn)制形式左(右)側(cè)有幾個(gè)0,遇到1就停止計(jì)數(shù)
計(jì)算int二進(jìn)制形式1的數(shù)量
左(右)移二進(jìn)制形式
按位(字節(jié))置換
計(jì)算int二進(jìn)制形式左(右)側(cè)有幾個(gè)0,遇到1就停止計(jì)數(shù)
//左側(cè) public static int numberOfLeadingZeros(int i) { // HD, Count leading 0"s if (i <= 0) return i == 0 ? 32 : 0; int n = 31; if (i >= 1 << 16) { n -= 16; i >>>= 16; } if (i >= 1 << 8) { n -= 8; i >>>= 8; } if (i >= 1 << 4) { n -= 4; i >>>= 4; } if (i >= 1 << 2) { n -= 2; i >>>= 2; } return n - (i >>> 1); } //右側(cè) public static int numberOfTrailingZeros(int i) { // HD, Figure 5-14 int y; if (i == 0) return 32; int n = 31; y = i <<16; if (y != 0) { n = n -16; i = y; } y = i << 8; if (y != 0) { n = n - 8; i = y; } y = i << 4; if (y != 0) { n = n - 4; i = y; } y = i << 2; if (y != 0) { n = n - 2; i = y; } return n - ((i << 1) >>> 31); }
左側(cè):numberOfLeadingZeros
1 負(fù)數(shù)1標(biāo)識(shí),左側(cè)無0,0全為0,直接返回32(int為32位)
2 通過1 << 16判斷,判斷條件為是否比它大,左邊16位是否全為0,決定接下來操作左或右半邊
3 再通過i << 8,4,2,1折半再折半計(jì)算出不為0的數(shù)字的位置,從而得出0的數(shù)量
右側(cè):numberOfTrailingZeros
通過i <<16,不為0則右邊有1,再i << 8,4,2,1,判斷出右邊數(shù)起的第一個(gè)1,從而計(jì)算出0的數(shù)量
計(jì)算int二進(jìn)制形式1的數(shù)量
public static int bitCount(int i) { // HD, Figure 5-2 i = i - ((i >>> 1) & 0x55555555); i = (i & 0x33333333) + ((i >>> 2) & 0x33333333); i = (i + (i >>> 4)) & 0x0f0f0f0f; i = i + (i >>> 8); i = i + (i >>> 16); return i & 0x3f; }
0x5 = 0101,通過做&運(yùn)算記錄雙數(shù)位的數(shù)據(jù)情況
0x3 = 0011,通過做&運(yùn)算記錄后兩位的數(shù)據(jù)情況
0x0f = 0000 1111,通過做&運(yùn)算記錄后四位的數(shù)據(jù)情況
1 int的二進(jìn)制形式的可能有 00,01,10,11
先做>>>右移一位再與01做&運(yùn)算,記錄了兩位二進(jìn)制左邊數(shù)字的1的數(shù)量,再用原來的二進(jìn)制數(shù)減去記錄的值
如11:11-01=10(11有兩個(gè)1)
2 經(jīng)過第一步計(jì)算,記錄了以兩位數(shù)為單位的1的數(shù)量
把第一步的結(jié)果與0011做&運(yùn)算得到四位二進(jìn)制結(jié)果的后兩位計(jì)算,0011再與四位二進(jìn)制結(jié)果>>>右移兩位計(jì)算前兩位的結(jié)果,再把其相加得到四位數(shù)中1的數(shù)量
如1011
1011 - 0101 = 0110
0001 + 0010 = 0011(1011有三個(gè)1)
3 i + (i >>> 4),i + (i >>> 8),i + (i >>> 16)分別把得到的上一步計(jì)算的結(jié)果整合計(jì)算
計(jì)算完成后記錄結(jié)果的有效位數(shù)只有右邊八位,32位數(shù)一共最多32個(gè)1,所以實(shí)際的有效位數(shù)只有右邊6位
左(右)移二進(jìn)制形式
public static int rotateLeft(int i, int distance) { return (i << distance) | (i >>> -distance); } public static int rotateRight(int i, int distance) { return (i >>> distance) | (i << -distance); }
移動(dòng)
調(diào)用<<或>>運(yùn)算符移動(dòng),同時(shí)通過 | >>> -distance得到移動(dòng)消逝的數(shù)據(jù),并將其放在補(bǔ)0的位置
-distance表示移動(dòng)-distance負(fù)數(shù)的表現(xiàn)形式int截取5位,long截取6位,如-1為32個(gè)1,截取5位為1 1111,為31,也就是不算位移,移動(dòng)的“路程”是32,正好把移出的數(shù)據(jù)再補(bǔ)回補(bǔ)0的地方
按位(字節(jié))置換
public static int reverseBytes(int i) { return (i << 24) | ((i & 0xff00) << 8) | ((i >>> 8) & 0xff00) | (i >>> 24); } public static int reverse(int i) { // HD, Figure 7-1 i = (i & 0x55555555) << 1 | (i >>> 1) & 0x55555555; i = (i & 0x33333333) << 2 | (i >>> 2) & 0x33333333; i = (i & 0x0f0f0f0f) << 4 | (i >>> 4) & 0x0f0f0f0f; return reverseBytes(i); }
按字節(jié)置換:reverseBytes
i << 24與i >>> 24做 | 運(yùn)算得到最左右兩邊的置換
0xff00二進(jìn)制形式為1111 1111 0000 0000
正好用來處理中間左八位和右八位的交換,主要是&和移動(dòng)的先后來實(shí)現(xiàn)不同的位的清零
按位置換:reverse
1 使用01來記錄兩位二進(jìn)制中的一位,再通過移動(dòng)記錄另一位,做 | 運(yùn)算的會(huì)把兩位的二進(jìn)制數(shù)交換位置
2 通過0011來交換四位中的前兩位和后兩位
3 通過0000 1111來交換前四位和后四位
4 通過前三步實(shí)現(xiàn)交換每8位的循序,再通過按字節(jié)置換交換全部的順序
Integer中還有關(guān)于
static final byte[] DigitTens = { "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "4", "4", "4", "4", "4", "4", "4", "4", "4", "4", "5", "5", "5", "5", "5", "5", "5", "5", "5", "5", "6", "6", "6", "6", "6", "6", "6", "6", "6", "6", "7", "7", "7", "7", "7", "7", "7", "7", "7", "7", "8", "8", "8", "8", "8", "8", "8", "8", "8", "8", "9", "9", "9", "9", "9", "9", "9", "9", "9", "9", } ; static final byte[] DigitOnes = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", } ;
這兩個(gè)數(shù)組的應(yīng)用和字符和byte之間轉(zhuǎn)換的精彩實(shí)現(xiàn),有時(shí)間會(huì)記錄。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/74526.html
摘要:作為條件變量的的不僅可以認(rèn)為內(nèi)嵌了一把鎖,還內(nèi)嵌了一個(gè)條件變量。操作條件變量的函數(shù)將當(dāng)前線程在條件變量上阻塞,一般是為了等待其他線程的某件事情執(zhí)行完成。其它裝箱類其它裝箱類的代碼這里就不分析了。重點(diǎn)關(guān)注下各裝箱類的緩存范圍。 jdk源碼讀到現(xiàn)在這里,重要的集合類也讀了一部分了。集合類再往下讀的話,就要涉及到兩個(gè)方向。第一,是比較典型的但是不常用的數(shù)據(jù)結(jié)構(gòu),這部分我準(zhǔn)備將數(shù)據(jù)結(jié)構(gòu)復(fù)習(xí)、回...
摘要:最近計(jì)劃把手冊(cè),認(rèn)真的先過一遍。語言參考類型新認(rèn)知強(qiáng)制轉(zhuǎn)換類型用。后期靜態(tài)綁定從這里開始語言參考生成器新認(rèn)知生成器汗水的核心是關(guān)鍵字。語言參考預(yù)定義變量超全局變量前一個(gè)錯(cuò)誤信息原始數(shù)據(jù)以上 showImg(https://segmentfault.com/img/remote/1460000010147451); 最近計(jì)劃把 PHP手冊(cè),認(rèn)真的先過一遍。記錄一些以前不知道,不明確的知識(shí)...
摘要:而且,與是一對(duì)多關(guān)系一個(gè)分類下有很多,一個(gè)只能歸屬于一個(gè)與是一對(duì)多關(guān)系一篇博客下有很多,一條只能歸屬于一篇與是多對(duì)多關(guān)系一篇有很多,一個(gè)下有很多。 說明:本文主要聊一聊Laravel測(cè)試數(shù)據(jù)填充器Seeder的小技巧,同時(shí)介紹下Laravel開發(fā)插件三件套,這三個(gè)插件挺好用哦。同時(shí),作者會(huì)將開發(fā)過程中的一些截圖和代碼黏上去,提高閱讀效率。 備注:在設(shè)計(jì)個(gè)人博客軟件時(shí),總會(huì)碰到有分類Ca...
摘要:加載因子是哈希表在其容量自動(dòng)增加之前可以達(dá)到多滿的一種尺度。當(dāng)哈希表中的條目數(shù)超出了加載因子與當(dāng)前容量的乘積時(shí),則要對(duì)該哈希表進(jìn)行操作即重建內(nèi)部數(shù)據(jù)結(jié)構(gòu),從而哈希表將具有大約兩倍的桶數(shù)。成員變量每個(gè)對(duì)由封裝,存在了對(duì)象數(shù)組中。 雖是讀書筆記,但是如轉(zhuǎn)載請(qǐng)注明出處 http://segmentfault.com/blog/exploring/ .. 拒絕伸手復(fù)制黨 LinkedLis...
摘要:那么,如果之后不是簡(jiǎn)單的操作,而是還有其它業(yè)務(wù)操作,之后才是,比如下面這樣,這該怎么辦呢其它業(yè)務(wù)操作這時(shí)候就沒辦法使用提供的方法了,只能業(yè)務(wù)自己來保證線程安全了,比如下面這樣其它業(yè)務(wù)操作這樣雖然不太友好,但是最起碼能保證業(yè)務(wù)邏輯是正確的。 刪除元素 刪除元素跟添加元素一樣,都是先找到元素所在的桶,然后采用分段鎖的思想鎖住整個(gè)桶,再進(jìn)行操作。 public V remove(Objec...
閱讀 2085·2021-11-23 10:08
閱讀 2423·2021-11-22 15:25
閱讀 3349·2021-11-11 16:55
閱讀 841·2021-11-04 16:05
閱讀 2748·2021-09-10 10:51
閱讀 769·2019-08-29 15:38
閱讀 1663·2019-08-29 14:11
閱讀 3572·2019-08-29 12:42