Java遍歷Map對象的七種方式

HashMap 遍歷從大的方向來說,可分爲以下 4 類:
1.For Each 方式遍歷;
2.迭代器(Iterator)方式遍歷;
3.Lambda 表達式遍歷(JDK 1.8+);
4.Streams API 遍歷(JDK 1.8+)。

但每種類型下又有不同的實現方式,因此具體的遍歷方式又可以分爲以下 7 種:
1.使用 For Each EntrySet 的方式進行遍歷;
2.使用 For Each KeySet 的方式進行遍歷;
3.使用迭代器(Iterator)EntrySet 的方式進行遍歷;
4.使用迭代器(Iterator)KeySet 的方式進行遍歷;
5.使用 Lambda 表達式的方式進行遍歷;
6.使用 Streams API 單線程的方式進行遍歷;
7.使用 Streams API 多線程的方式進行遍歷。

接下來我們來看每種遍歷方式的具體實現代碼:

方式一 使用For Each EntrySet 這是最常見的並且在大多數情況下也是最可取的遍歷方式。在鍵值都需要時使用。

Map<Integer, Integer> map = new HashMap<Integer, Integer>(); 
for (Map.Entry<Integer, Integer> entry : map.entrySet()) { 
  System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue()); 
}

方法二 使用For Each KeySet 在for-each循環中遍歷keys或values。
如果只需要map中的鍵或者值,你可以通過keySet或values來實現遍歷,而不是用entrySet。

Map<Integer, Integer> map = new HashMap<Integer, Integer>(); 
//遍歷map中的鍵 
for (Integer key : map.keySet()) { 
  Integer value = map.get(key); 
  System.out.println("Key = " + key); 
} 
//遍歷map中的值 
for (Integer value : map.values()) { 
  System.out.println("Value = " + value); 
}

該方法比entrySet遍歷在性能上稍好(快了10%),而且代碼更加乾淨。

**方法三 使用Iterator EntrySet遍歷,即使用泛型 **

Map<Integer, Integer> map = new HashMap<Integer, Integer>(); 
Iterator<Map.Entry<Integer, Integer>> entries = map.entrySet().iterator(); 
while (entries.hasNext()) { 
  Map.Entry<Integer, Integer> entry = entries.next(); 
  System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue()); 
}

**方法四 使用Iterator KeySet 遍歷 **

Map map = new HashMap(); 
Iterator entries = map.entrySet().iterator(); 
while (entries.hasNext()) { 
  Map.Entry entry = (Map.Entry) entries.next(); 
  Integer key = (Integer)entry.getKey(); 
  Integer value = (Integer)entry.getValue(); 
  System.out.println("Key = " + key + ", Value = " + value); 
}

你也可以在keySet和values上應用同樣的方法。

該種方式看起來冗餘卻有其優點所在。首先,在老版本java中這是惟一遍歷map的方式。另一個好處是,你可以在遍歷時調用iterator.remove()來刪除entries,另兩個方法則不能。根據javadoc的說明,如果在for-each遍歷中嘗試使用此方法,結果是不可預測的。

從性能方面看,該方法類同於for-each遍歷(即方法二)的性能。

方法五 使用 Lambda 表達式的方式進行遍歷

Map map = new HashMap(); 
map.forEach((key, value) -> {
	System.out.println(key);
	System.out.println(value);
});

方法六 使用 Streams API 單線程的方式進行遍歷

Map map = new HashMap(); 
map.entrySet().stream().forEach((entry) -> {
	System.out.println(entry.getKey());
	System.out.println(entry.getValue());
});

方法七 使用 Streams API 多線程的方式進行遍歷

Map map = new HashMap(); 
map.entrySet().parallelStream().forEach((entry) -> {
	System.out.println(entry.getKey());
	System.out.println(entry.getValue());
});

總結

性能測試,比較一下這 7 種循環的性能。

因爲 parallelStream 爲多線程版本性能一定是最好的,所以就不參與測試了,其他 6 個方法的測試結果如下:
在這裏插入圖片描述
其中 Units 爲 ns/op 意思是執行完成時間(單位爲納秒),而 Score 列爲平均執行時間, ± 符號表示誤差。從以上結果可以看出,兩個 entrySet 的性能相近,並且執行速度最快,接下來是 stream ,然後是兩個 keySet,性能最差的是 KeySet 。

所有優先使用的順序爲:
Streams API 多線程 > 迭代器(Iterator)EntrySet > For Each EntrySet > For Each KeySet > 迭代器(Iterator)KeySet > Lambda 表達式 > Streams API 單線程

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章