您好,登錄后才能下訂單哦!
Java 中HashMap初始化的另一種方式是怎么,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
如果你接觸過不同的語言,從語法和代碼層面來說,Java 是一種不折不扣的“臃腫、啰嗦”的語言,從另一方面來說這種臃腫和啰嗦也體現了它嚴謹的一面,作為適合構建大型、復雜項目的理由之一。
HashMap 是一種常用的數據結構,一般用來做數據字典或者 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"); } };
嗯,看起來優雅了不少,一步到位,一氣呵成的趕腳。然后問題來了,有童鞋會問:納尼?這里的雙括號到底什么意思,什么用法呢?哈哈,其實很簡單,看看下面的代碼你就知道啥意思了。
public class Test { /*private static HashMap<String, String> map = new HashMap<String, String>() { { put("Name", "June"); put("QQ", "2572073701"); } };*/ public Test() { System.out.println("Constructor called:構造器被調用"); } static { System.out.println("Static block called:靜態塊被調用"); } { System.out.println("Instance initializer called:實例初始化塊被調用"); } public static void main(String[] args) { new Test(); System.out.println("======================="); new Test(); } }
output:
Static block called:靜態塊被調用 Instance initializer called:實例初始化被調用 Constructor called:構造器被調用 ======================= Instance initializer called:實例初始化被調用 Constructor called:構造器被調用
Note:關于 static 的作用與用法如果不了解,請參考:
http://my.oschina.net/leejun2005/blog/193439#OSC_h4_1 為什么 main 方法是 public static void?
http://my.oschina.net/leejun2005/blog/144349#OSC_h4_2 設計模式之:聊聊 java 中的單例模式(Singleton)
也就是說第一層括弧實際是定義了一個匿名內部類 (Anonymous Inner Class),第二層括弧實際上是一個實例初始化塊 (instance initializer block),這個塊在內部匿名類構造時被執行。這個塊之所以被叫做“實例初始化塊”是因為它們被定義在了一個類的實例范圍內。
上面代碼如果是寫在 Test 類中,編譯后你會看到會生成 Test$1.class 文件,反編譯該文件內容:
D:\eclipse_indigo\workspace_home\CDHJobs\bin\pvuv\>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.java package pvuv.zhaopin; import java.util.HashMap; // Referenced classes of package pvuv.zhaopin: // Test class Test$1 extends HashMap // 創建了一個 HashMap 的子類 { Test$1() { // 第二個 {} 中的代碼放到了構造方法中去了 put("Name", "June"); put("QQ", "2572073701"); } } D:\eclipse_indigo\workspace_home\CDHJobs\bin\pvuv\>
這種寫法,推而廣之,在初始化 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]
在 Java 7 中你可以像 Ruby, Perl、Python 一樣創建 collections 了。
Note:這些集合是不可變的。
PS:由于原文[5]作者并沒有標出 java 7 哪個小版本號引入的這些新特性,對于留言報錯的同學,請嘗試大于 1.7.0_09 或者 java8 試試?
List<String> list = new ArrayList<String>(); list.add("item"); String item = list.get(0); Set<String> set = new HashSet<String>(); set.add("item"); Map<String, Integer> map = new HashMap<String, Integer>(); map.put("key", 1); int value = map.get("key"); // 現在你還可以: List<String> list = ["item"]; String item = list[0]; Set<String> set = {"item"}; Map<String, Integer> map = {"key" : 1}; int value = map["key"];
文章開頭提到的文藝寫法的好處很明顯就是一目了然。這里來羅列下此種方法的壞處,如果這個對象要串行化,可能會導致串行化失敗。
1.此種方式是匿名內部類的聲明方式,所以引用中持有著外部類的引用。所以當時串行化這個集合時外部類也會被不知不覺的串行化,當外部類沒有實現serialize接口時,就會報錯。
2.上例中,其實是聲明了一個繼承自HashMap的子類。然而有些串行化方法,例如要通過Gson串行化為json,或者要串行化為xml時,類庫中提供的方式,是無法串行化Hashset或者HashMap的子類的,從而導致串行化失敗。解決辦法:重新初始化為一個HashMap對象:
new HashMap(map);
這樣就可以正常初始化了。
當一種新的工具或者寫法出現時,猿們都會來一句:性能怎么樣?(這和男生談論妹紙第一句一般都是:“長得咋樣?三圍多少?”一個道理:))
關于這個兩種寫法我這邊筆記本上測試文藝寫法、普通寫法分別創建 10,000,000 個 Map 的結果是 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>() { { put("Name", "June"); put("QQ", "2572073701"); } }; } System.out.println(System.currentTimeMillis() - st); // 1217 */ 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 } }
從代碼上看,a 為什么可以不先聲明類型?你覺得 a、b、c 的值分別是多少?能說明理由么?
TIPS:如果你對這塊機制不了解,建議試著反編譯一下字節碼文件。
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()); } }
// 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.java import 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 - \u6210\u5458\u53D8\u91CF\uFF1A")).append(this.h).toString()); System.out.println((new StringBuilder("h - \u5C40\u90E8\u53D8\u91CF: ")).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; } }
a: 33 b: 22 c: 11 d: 44 f: 5 e: 6 h - 成員變量:8 h - 局部變量: 88 g: 77
關于Java 中HashMap初始化的另一種方式是怎么問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。