溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java 中HashMap初始化的另一種方式是怎么

發(fā)布時間:2021-10-12 09:14:25 來源:億速云 閱讀:124 作者:柒染 欄目:云計算

Java 中HashMap初始化的另一種方式是怎么,針對這個問題,這篇文章詳細介紹了相對應(yīng)的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

如果你接觸過不同的語言,從語法和代碼層面來說,Java 是一種不折不扣的“臃腫、啰嗦”的語言,從另一方面來說這種臃腫和啰嗦也體現(xiàn)了它嚴(yán)謹?shù)囊幻?,作為適合構(gòu)建大型、復(fù)雜項目的理由之一。

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 {

    /*private static HashMap<String, String> map = new HashMap<String, String>() {
        {
            put("Name", "June");
            put("QQ", "2572073701");
        }
    };*/

    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();

    }
}

output:

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)用

Note:關(guān)于 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  設(shè)計模式之:聊聊 java 中的單例模式(Singleton)

也就是說第一層括弧實際是定義了一個匿名內(nèi)部類 (Anonymous Inner Class),第二層括弧實際上是一個實例初始化塊 (instance initializer block),這個塊在內(nèi)部匿名類構(gòu)造時被執(zhí)行。這個塊之所以被叫做“實例初始化塊”是因為它們被定義在了一個類的實例范圍內(nèi)。
上面代碼如果是寫在 Test 類中,編譯后你會看到會生成 Test$1.class 文件,反編譯該文件內(nèi)容:

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  // 創(chuàng)建了一個 HashMap 的子類
{

    Test$1()
    {                        //  第二個 {} 中的代碼放到了構(gòu)造方法中去了 
        put("Name", "June");
        put("QQ", "2572073701");
    }
}

D:\eclipse_indigo\workspace_home\CDHJobs\bin\pvuv\>

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、Java7:增加對 collections 的支持

在 Java 7 中你可以像 Ruby, Perl、Python 一樣創(chuàng)建 collections 了。

Note:這些集合是不可變的。

PS:由于原文[5]作者并沒有標(biāo)出 java 7 哪個小版本號引入的這些新特性,對于留言報錯的同學(xué),請嘗試大于 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");

// 現(xiàn)在你還可以: 

List<String> list = ["item"];
String item = list[0];
		
Set<String> set = {"item"};
		
Map<String, Integer> map = {"key" : 1};
int value = map["key"];

4、文藝寫法的潛在問題

文章開頭提到的文藝寫法的好處很明顯就是一目了然。這里來羅列下此種方法的壞處,如果這個對象要串行化,可能會導(dǎo)致串行化失敗。
1.此種方式是匿名內(nèi)部類的聲明方式,所以引用中持有著外部類的引用。所以當(dāng)時串行化這個集合時外部類也會被不知不覺的串行化,當(dāng)外部類沒有實現(xiàn)serialize接口時,就會報錯。
2.上例中,其實是聲明了一個繼承自HashMap的子類。然而有些串行化方法,例如要通過Gson串行化為json,或者要串行化為xml時,類庫中提供的方式,是無法串行化Hashset或者HashMap的子類的,從而導(dǎo)致串行化失敗。解決辦法:重新初始化為一個HashMap對象:
 

new HashMap(map);

這樣就可以正常初始化了。

5、執(zhí)行效率問題

當(dāng)一種新的工具或者寫法出現(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>() {
                {
                    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
    }
}

6、由實例初始化塊聯(lián)想到的一些變量初始化問題

從代碼上看,a 為什么可以不先聲明類型?你覺得 a、b、c 的值分別是多少?能說明理由么?

TIPS:如果你對這塊機制不了解,建議試著反編譯一下字節(jié)碼文件。

6.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());
    }

}
6.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.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;
    }
}
6.3 output:
a: 33
b: 22
c: 11
d: 44
f: 5
e: 6
h - 成員變量:8
h - 局部變量: 88
g: 77

關(guān)于Java 中HashMap初始化的另一種方式是怎么問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識。

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI