測試環境:jdk1.7.0_79\Processor 1.7 GHz Intel Core i5服務器
遍歷Map的方式有不少,一般場景下咱們須要的是遍歷Map中的Key和Value。併發
更新:增長一個方法對方法一優化,採用foreach循環測試
寫了四個方法:優化
/**spa
* while循環 map.entrySet().iterator()獲取map的valuecode
* @param mapblog
*/get
public static void getMap1(Map<String,String> map){it
Iterator<Map.Entry<String, String>> iter = map.entrySet().iterator();io
while (iter.hasNext()) {
Map.Entry<String, String> entry = iter.next();
String key = entry.getKey();
String value = entry.getValue();
}
}
/**
* while循環 map.keySet().iterator()獲取map的value
* @param map
*/
public static void getMap2(Map<String,String> map){
Iterator<String> it = map.keySet().iterator();
while (it.hasNext()) {
String key = it.next();
String value = map.get(key);
}
}
/**
* foreach循環map.entrySet()獲取map的value
* getMap1的另外一種寫法,採用foreach循環.foreach循環的底層實現原理就是迭代器Iterator
* @param map
*/
public static void getMap3(Map<String,String> map){
Set<Map.Entry<String, String>> set = map.entrySet();
for (Map.Entry<String, String> entry : set) {
String value = entry.getValue();
}
}
/**
* foreach循環map.keySet()獲取map的value
* @param map
*/
public static void getMap4(Map<String,String> map){
Set<String> set = map.keySet();
for (String entry : set) {
String value = map.get(entry);
}
}
注:我之前經常使用的就是方法2,原則就是能用就行。因此第一印象不必定對哦。
默認map中已經存儲了數據,map數據量不肯定,用戶訪問量不肯定
我採用for循環屢次調用getMap方法來模擬用戶訪問,以下:
HashMap<String, String> map = new HashMap<String, String>();
int mapNum=1000;//設置map數據量
int forNum = 1000;//設置for循環調用次數,模擬用戶訪問次數
//模擬map已經存儲了數據
for (int i = 0; i < mapNum; i++) {
map.put("key" + i, "value" + i);
}
//用for循環調用getMap來模擬屢次訪問
long startTime = System.currentTimeMillis();
for (int i = 0; i < forNum; i++) {
getMap1(map);
}
System.out.println("getMap1:"+(System.currentTimeMillis() - startTime) + "ms");
startTime = System.currentTimeMillis();
for (int i = 0; i < forNum; i++) {
getMap2(map);
}
System.out.println("getMap2:"+(System.currentTimeMillis() - startTime) + "ms");
startTime = System.currentTimeMillis();
for (int i = 0; i < forNum; i++) {
getMap3(map);
}
System.out.println("getMap3:"+(System.currentTimeMillis() - startTime) + "ms");
startTime = System.currentTimeMillis();
for (int i = 0; i < forNum; i++) {
getMap4(map);
}
System.out.println("getMap4:"+(System.currentTimeMillis() - startTime) + "ms");
(如下測試數據是前三個方法的數據,方法四也相似的結果)
map數據量爲10,用戶訪問10次(for循環調用getMap 10次)
看不出來效果
map數據量爲10,用戶訪問100次(for循環調用getMap 100次)
看不出來效果
map數據量爲10,用戶訪問1000次(for循環調用getMap 1000次)
getMap1:15ms
getMap2:22ms
getMap3:4ms
map數據量爲10,用戶訪問10000次(for循環調用getMap 10000次)
getMap1:27ms
getMap2:31ms
getMap3:15ms
map數據量爲10,用戶訪問100000次(for循環調用getMap 10萬次)
getMap1:52ms
getMap2:53ms
getMap3:32ms
map數據量爲10,用戶訪問1000000次(for循環調用getMap 百萬次)
getMap1:169ms
getMap2:280ms
getMap3:128ms
百萬級別的時候差距拉大了,但有時候1和3差距不大
map數據量爲100,for循環調用getMap 100次
getMap1:8ms
getMap2:18ms
getMap3:4ms
一倍差距啊
map數據量爲100,for循環調用getMap 1000次
getMap1:23ms
getMap2:28ms
getMap3:14ms
map數據量爲100,for循環調用getMap 1萬次
getMap1:38ms
getMap2:57ms
getMap3:28ms
map數據量爲100,for循環調用getMap 10萬次
getMap1:126ms
getMap2:221ms
getMap3:75ms
map數據量爲100,for循環調用getMap 百萬次
getMap1:641ms
getMap2:1823ms
getMap3:574ms
1和2三倍啊!,不過這個時候1和3差距不大了
後面僅僅是摘選幾條:
map數據量爲1000,for循環調用getMap 1000次
getMap1:44ms
getMap2:43ms
getMap3:26ms
map數據量爲1000,for循環調用getMap 是萬次
getMap1:1259ms
getMap2:2420ms
getMap3:887ms
map數據量爲1000,for循環調用getMap 百萬次
getMap1:11210ms
getMap2:21083ms
getMap3:6941ms
map數據量爲10000,for循環調用getMap 10000次
getMap1:2807ms
getMap2:4770ms
getMap3:2511ms
map數據量爲10000,for循環調用getMap 百萬次
getMap1:167107ms
getMap2:230967ms
getMap3:123263ms
基本上方法一的效率和四差很少,比方法二高一倍,方法三比方法一效率高一些,建議採用方法三。固然實際狀況可能很複雜,硬件設備、併發狀況,更多的時候僅僅是map數據量大可是訪問量小,甚至可能咱們採用服務器啓動即加載的方式避免了用戶訪問時遍歷。
並且要注意,不一樣狀況下的寫法不一樣,測試結果多是不同的。須要注重的是,一旦涉及到遍歷的狀況,就要考慮數據量和訪問量,來選擇最佳的遍歷方式。
順便提一句:有些人可能習慣這樣寫代碼
for(int i = 0;i < list.length();i++){}以及foreach語句,我印象中for循環中每次都要計算一次list.length,這也是沒必要要的開銷。foreach在順序訪問中效率高,因此若是是遍歷arrayList的時候不要用foreach
更新:若是隻是想要遍歷一下key呢?方法三不必定比方法二好,方法一確定比方法二差。例如
map數據量爲10000,for循環調用getMap 10000次
getMap1:2767ms
getMap2:1068ms
getMap3:2208ms
根據實際狀況選擇吧。
歡迎各位補充。