雙括號,你可能沒用過這種方式的集合
關(guān)于【雙括號】,你可能沒用過這種方式的集合,今天黛兒小編給您分享一下,如果對您有所幫助別忘了關(guān)注本站哦。
?
<>()()〈〉??﹛﹜『』〖〗[]《》﹝﹞〔〕{}「」【】︵︶︷︸︿﹀︹︺︽︾﹁﹂﹃﹄︻︼
- 推薦閱讀:
你可能沒用過這種方式的集合!newHashMap(省略號)
來源:https://blog.csdn.net/luman1991/article/details/53034602
一、HashMap的初始化
1、HashMap 初始化的文藝寫法
HashMap 是一種常用的數(shù)據(jù)結(jié)構(gòu),一般用來做數(shù)據(jù)字典或者 Hash 查找的容器。普通青年一般會這么初始化:
HashMap<String, String> map = new HashMap<String, String>();map.put("Name", "June");map.put("QQ", "2572073701");
看完這段代碼,很多人都會覺得這么寫太啰嗦了,對此,文藝青年一般這么來了:
HashMap<String, String> map = new HashMap<String, String>() { { put("Name", "June"); put("QQ", "2572073701"); } };
嗯,看起來優(yōu)雅了不少,一步到位,一氣呵成的趕腳。然后問題來了,有童鞋會問:納尼?這里的雙括號到底什么意思,什么用法呢?哈哈,其實很簡單,看看下面的代碼你就知道啥意思了。
public class Test { public Test() { System.out.println("Constructor called:構(gòu)造器被調(diào)用"); } static { System.out.println("Static block called:靜態(tài)塊被調(diào)用"); } { System.out.println("Instance initializer called:實例初始化塊被調(diào)用"); } public static void main(String[] args) { new Test(); System.out.println("======================="); new Test(); }}
輸出:
Static block called:靜態(tài)塊被調(diào)用Instance initializer called:實例初始化被調(diào)用Constructor called:構(gòu)造器被調(diào)用=======================Instance initializer called:實例初始化被調(diào)用Constructor called:構(gòu)造器被調(diào)用
也就是說第一層括弧實際是定義了一個匿名內(nèi)部類 (Anonymous Inner Class),第二層括弧實際上是一個實例初始化塊 (instance initializer block),這個塊在內(nèi)部匿名類構(gòu)造時被執(zhí)行。這個塊之所以被叫做“實例初始化塊”是因為它們被定義在了一個類的實例范圍內(nèi)。
上面代碼如果是寫在 Test 類中,編譯后你會看到會生成 Test$1.class 文件,反編譯該文件內(nèi)容:
D:eclipse_indigoworkspace_homeCDHJobsbinpvuv>jad -p Test$1.class// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.// Jad home page: http://www.kpdus.com/jad.html// Decompiler options: packimports(3)// Source File Name: Test.javapackage pvuv.zhaopin;import java.util.HashMap;// Referenced classes of package pvuv.zhaopin:// Test class Test$1 extends HashMap // 創(chuàng)建了一個 HashMap 的子類 { Test$1() { // 第二個 {} 中的代碼放到了構(gòu)造方法中去了 put("Name", "June"); put("QQ", "2572073701"); } }D:eclipse_indigoworkspace_homeCDHJobsbinpvuv>
2、推而廣之
這種寫法,推而廣之,在初始化 ArrayList、Set 的時候都可以這么玩,比如你還可以這么玩:
List<String> names = new ArrayList<String>() { { for (int i = 0; i < 10; i++) { add("A" + i); } }};System.out.println(names.toString()); // [A0, A1, A2, A3, A4, A5, A6, A7, A8, A9]
3、文藝寫法的潛在問題
文章開頭提到的文藝寫法的好處很明顯就是一目了然。這里來羅列下此種方法的壞處,如果這個對象要串行化,可能會導致串行化失敗。
- 此種方式是匿名內(nèi)部類的聲明方式,所以引用中持有著外部類的引用。所以當串行化這個集合時外部類也會被不知不覺的串行化,當外部類沒有實現(xiàn)serialize接口時,就會報錯。
- 上例中,其實是聲明了一個繼承自HashMap的子類。然而有些串行化方法,例如要通過Gson串行化為json,或者要串行化為xml時,類庫中提供的方式,是無法串行化Hashset或者HashMap的子類的,從而導致串行化失敗。
解決辦法,重新初始化為一個HashMap對象:
new HashMap(map);
這樣就可以正常初始化了。
4、執(zhí)行效率問題
當一種新的工具或者寫法出現(xiàn)時,猿們都會來一句:性能怎么樣?(這和男生談?wù)撁眉埖谝痪湟话愣际牵骸伴L得咋樣?三圍多少?”一個道理:))
關(guān)于這個兩種寫法我這邊筆記本上測試文藝寫法、普通寫法分別創(chuàng)建 10,000,000 個 Map 的結(jié)果是 1217、1064,相差 13%。
public class Test { public static void main(String[] args) { long st = System.currentTimeMillis(); for (int i = 0; i < 10000000; i++) { HashMap<String, String> map = new HashMap<String, String>(); map.put("Name", "June"); map.put("QQ", "2572073701"); } System.out.println(System.currentTimeMillis() - st); // 1064 }}
5、由實例初始化塊聯(lián)想到的一些變量初始化問題
從代碼上看,a 為什么可以不先聲明類型?你覺得 a、b、c 的值分別是多少?能說明理由么?TIP:如果你對這塊機制不了解,建議試著反編譯一下字節(jié)碼文件。
5.1 測試源碼
public class Test { int e = 6; Test() { int c = 1; this.f = 5; int e = 66; } int f = 55; int c = 11; int b = 1; { a = 3; b = 22; } int a =33; static { d = 4; } static int d = 44; int g = 7; int h = 8; public int test() { g = 77; int h = 88; System.out.println("h - 成員變量:" + this.h); System.out.println("h - 局部變量: " + h); return g; } public static void main(String[] args) { System.out.println("a: " + new Test().a); System.out.println("b: " + new Test().b); System.out.println("c: " + new Test().c); System.out.println("d: " + new Test().d); System.out.println("f: " + new Test().f); System.out.println("e: " + new Test().e); System.out.println("g: " + new Test().test()); }}
5.2 字節(jié)碼反編譯:
// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.// Jad home page: http://www.kpdus.com/jad.html// Decompiler options: packimports(3)// Source File Name: Test.javaimport java.io.PrintStream;public class Test{ Test() { this.e = 6; f = 55; this.c = 11; b = 1; a = 3; b = 22; a = 33; g = 7; h = 8; int c = 1; f = 5; int e = 66; } public int test() { g = 77; int h = 88; System.out.println((new StringBuilder("h - u6210u5458u53D8u91CFuFF1A")).append(this.h).toString()); System.out.println((new StringBuilder("h - u5C40u90E8u53D8u91CF: ")).append(h).toString()); return g; } public static void main(String args[]) { System.out.println((new StringBuilder("a: ")).append((new Test()).a).toString()); System.out.println((new StringBuilder("b: ")).append((new Test()).b).toString()); System.out.println((new StringBuilder("c: ")).append((new Test()).c).toString()); new Test(); System.out.println((new StringBuilder("d: ")).append(d).toString()); System.out.println((new StringBuilder("f: ")).append((new Test()).f).toString()); System.out.println((new StringBuilder("e: ")).append((new Test()).e).toString()); System.out.println((new StringBuilder("g: ")).append((new Test()).test()).toString()); } int e; int f; int c; int b; int a; static int d = 4; int g; int h; static { d = 44; }}
5.3 輸出結(jié)果:
a: 33 b: 22 c: 11 d: 44 f: 5 e: 6 h - 成員變量:8 h - 局部變量: 88 g: 77
二、HashMap遍歷方法示例
第一種:
Map map = new HashMap();Iterator iter = map.entrySet().iterator();while (iter.hasNext()) { Map.Entry entry = (Map.Entry) iter.next(); Object key = entry.getKey(); Object val = entry.getValue();}
效率高,以后一定要使用此種方式!
第二種:
Map map = new HashMap();Iterator iter = map.keySet().iterator();while (iter.hasNext()) { Object key = iter.next(); Object val = map.get(key);}
效率低,以后盡量少使用!
HashMap的遍歷有兩種常用的方法,那就是使用keyset及entryset來進行遍歷,但兩者的遍歷速度是有差別的,下面請看實例:
public class HashMapTest { public static void main(String[] args) { HashMap hashmap = new HashMap(); for (int i = 0; i < 1000; i++) { hashmap.put("" + i, "thanks"); } long bs = Calendar.getInstance().getTimeInMillis(); Iterator iterator = hashmap.keySet().iterator(); while (iterator.hasNext()) { System.out.print(hashmap.get(iterator.next())); } System.out.println(); System.out.println(Calendar.getInstance().getTimeInMillis() - bs); listHashMap(); } public static void listHashMap() { HashMap hashmap = new HashMap(); for (int i = 0; i < 1000; i++) { hashmap.put("" + i, "thanks"); } long bs = Calendar.getInstance().getTimeInMillis(); java.util.Iterator it = hashmap.entrySet().iterator(); while (it.hasNext()) { java.util.Map.Entry entry = (java.util.Map.Entry) it.next(); // entry.getKey() 返回與此項對應(yīng)的鍵 // entry.getValue() 返回與此項對應(yīng)的值 System.out.print(entry.getValue()); } System.out.println(); System.out.println(Calendar.getInstance().getTimeInMillis() - bs); }}
對于keySet其實是遍歷了2次,一次是轉(zhuǎn)為iterator,一次就從hashmap中取出key所對于的value。而entryset只是遍歷了第一次,他把key和value都放到了entry中,所以就快了。
注:Hashtable的遍歷方法和以上的差不多!
本文關(guān)鍵詞:雙括號《^o^》怎么打出來,雙括號是什么符號,雙括號在電腦上怎么打,雙括號電腦鍵盤怎么打出來,雙括號的用法。這就是關(guān)于《雙括號,你可能沒用過這種方式的集合》的所有內(nèi)容,希望對您能有所幫助!更多的知識請繼續(xù)關(guān)注我們!
版權(quán)聲明: 本站僅提供信息存儲空間服務(wù),旨在傳遞更多信息,不擁有所有權(quán),不承擔相關(guān)法律責任,不代表本網(wǎng)贊同其觀點和對其真實性負責。如因作品內(nèi)容、版權(quán)和其它問題需要同本網(wǎng)聯(lián)系的,請發(fā)送郵件至 舉報,一經(jīng)查實,本站將立刻刪除。