一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - 舉例詳解Java編程中HashMap的初始化以及遍歷的方法

舉例詳解Java編程中HashMap的初始化以及遍歷的方法

2020-01-13 17:26goldensun JAVA教程

這篇文章主要介紹了Java編程中HashMap的初始化以及遍歷的方法,是Java入門學習中的基礎知識,需要的朋友可以參考下

一、HashMap的初始化
1、HashMap 初始化的文藝寫法
   HashMap 是一種常用的數據結構,一般用來做數據字典或者 Hash 查找的容器。普通青年一般會這么初始化:

 

?
1
2
3
4
HashMap<String, String> map =
  new HashMap<String, String>();
 map.put("Name", "June");
 map.put("QQ", "2572073701");

看完這段代碼,很多人都會覺得這么寫太啰嗦了,對此,文藝青年一般這么來了:
 

?
1
2
3
4
5
6
7
HashMap<String, String> map =
  new HashMap<String, String>() {
 {
 put("Name", "June");
 put("QQ", "2572073701");
 }
 };

   嗯,看起來優雅了不少,一步到位,一氣呵成的趕腳。然后問題來了,有童鞋會問:納尼?這里的雙括號到底什么意思,什么用法呢?哈哈,其實很簡單,看看下面的代碼你就知道啥意思了。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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();
 }
}

輸出:

?
1
2
3
4
5
6
Static block called:靜態塊被調用
Instance initializer called:實例初始化被調用
Constructor called:構造器被調用
=======================
Instance initializer called:實例初始化被調用
Constructor called:構造器被調用

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

?
1
D:\eclipse_indigo\workspace_home\CDHJobs\bin\pvuv\>jad -p Test$1.class
?
1
2
3
4
// 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
?
1
2
3
4
5
6
7
8
9
10
11
12
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");
 }
 }
?
1
D:\eclipse_indigo\workspace_home\CDHJobs\bin\pvuv\>

2、推而廣之
  這種寫法,推而廣之,在初始化 ArrayList、Set 的時候都可以這么玩,比如你還可以這么玩:

?
1
2
3
4
5
6
7
8
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 一樣創建 collections 了。
Note:這些集合是不可變的。

PS:由于原文[5]作者并沒有標出 java 7 哪個小版本號引入的這些新特性,對于留言報錯的同學,請嘗試大于 1.7.0_09 或者 java8 試試?

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
List list = new ArrayList();
 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"];

4、文藝寫法的潛在問題
    文章開頭提到的文藝寫法的好處很明顯就是一目了然。這里來羅列下此種方法的壞處,如果這個對象要串行化,可能會導致串行化失敗。
  1.此種方式是匿名內部類的聲明方式,所以引用中持有著外部類的引用。所以當串行化這個集合時外部類也會被不知不覺的串行化,當外部類沒有實現serialize接口時,就會報錯。

2.上例中,其實是聲明了一個繼承自HashMap的子類。然而有些串行化方法,例如要通過Gson串行化為json,或者要串行化為xml時,類庫中提供的方式,是無法串行化Hashset或者HashMap的子類的,從而導致串行化失敗。解決辦法:重新初始化為一個HashMap對象:

?
1
new HashMap(map);

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

5、執行效率問題
   當一種新的工具或者寫法出現時,猿們都會來一句:性能怎么樣?(這和男生談論妹紙第一句一般都是:“長得咋樣?三圍多少?”一個道理:))
關于這個兩種寫法我這邊筆記本上測試文藝寫法、普通寫法分別創建 10,000,000 個 Map 的結果是 1217、1064,相差 13%。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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、由實例初始化塊聯想到的一些變量初始化問題
  從代碼上看,a 為什么可以不先聲明類型?你覺得 a、b、c 的值分別是多少?能說明理由么?
TIPS:如果你對這塊機制不了解,建議試著反編譯一下字節碼文件。

6.1 測試源碼

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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 字節碼反編譯:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// 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


二、HashMap遍歷方法示例
第一種:
  

?
1
2
3
4
5
6
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();
  }

  效率高,以后一定要使用此種方式!
  第二種:
 

?
1
2
3
4
5
6
Map map = new HashMap();
 Iterator iter = map.keySet().iterator();
 while (iter.hasNext()) {
 Object key = iter.next();
 Object val = map.get(key);
 }

  效率低,以后盡量少使用!
  HashMap的遍歷有兩種常用的方法,那就是使用keyset及entryset來進行遍歷,但兩者的遍歷速度是有差別的,下面請看實例:
 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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() ...{
 java.util.HashMap hashmap = new java.util.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() 返回與此項對應的鍵
 // entry.getValue() 返回與此項對應的值
 System.out.print(entry.getValue());
 }
 System.out.println();
 System.out.println(Calendar.getInstance().getTimeInMillis() - bs);
 }
 }

  對于keySet其實是遍歷了2次,一次是轉為iterator,一次就從hashmap中取出key所對于的value。而entryset只是遍歷了第一次,他把key和value都放到了entry中,所以就快了。
  注:Hashtable的遍歷方法和以上的差不多!

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 免费午夜影院 | 美女叽叽 | 婷婷在线观看香蕉五月天 | 免费高清资源黄网站在线观看 | 99久久精品免费精品国产 | 蜜桃在线 | 久久精品一卡二卡三卡四卡视频版 | 2021日产国产麻豆 | 美女胸又大又黄又www小说 | 国产一区二区三区免费在线视频 | 精品麻豆国产 | 色综合伊人色综合网站中国 | 成 人 亚洲 综合天堂 | 日本ww视频 | 91综合精品网站久久 | 精品国产欧美一区二区五十路 | 亚洲qvod图片区电影 | 喜欢老头吃我奶躁我的动图 | 欧美日韩在线观看精品 | 99re7在线精品免费视频 | 2018亚洲男人天堂 | 青青青在线免费 | 日本人在线看片 | 成全动漫视频在线观看 | 色多多视频网站 | 高清不卡日本v在线二区 | 欧美日韩在线观看区一二 | 精品亚洲一区二区三区在线播放 | 欧美一区二区三 | 精品区2区3区4区产品乱码9 | 欧美日韩高清不卡一区二区三区 | 日本性漫画 | www.爱操| 成人在线一区二区 | 久久伊人免费 | 色先锋影音先锋 | 亚洲乱码一区二区三区国产精品 | 国产视频自拍一区 | 免费观看小视频 | 日本漫画无翼乌 | 久久精品黄AA片一区二区三区 |