哪種Map遍歷方法更優?!—Map遍歷方法的正確選擇
我們都知道遍歷Map一般有3種方法,values(),keySet()和entrySet(),常見的是keySet用的多,簡單容易理解,entrySet()是返回Map中的靜態內部類Entry類型別的Set例項,當然了你別說forEach,forEach只是一種代替for(int i=0;;)和while()遍歷的一種方式,底層也是用迭代器實現的,只不過把部分東西隱藏了,建議大家平常開發中能用forEach遍歷,儘可能的用這個,《Effective java》中也明確表示了,簡單而不容易出錯。
如果Map中有大量的元素,而且併發量又很高,這就涉及到採用哪種遍歷方法的問題,下面就來測試一下:
- Map<String,String> mapTest=
- for(int i=0;i<10000;i++){
- mapTest.put(String.valueOf(i),String.valueOf(i) );
- }
- //一種遍歷,keySet()方法
- long start=System.nanoTime();
- Set<String> setEach=mapTest.keySet();
- for(String key:setEach){
- String value=mapTest.get(key);
- }
- long end=System.nanoTime();
- System.out.println("keySet遍歷map耗時"+(end-start)/1000+"微秒");
- //二種遍歷,可用values()返回Collection<T>,不容易得到對應的key
- start=System.nanoTime();
- Collection<String> co=mapTest.values();
- for(String value:co){
- //遍歷中也在建立value
- }
- end=System.nanoTime();
- System.out.println("values遍歷map(只得到值)耗時"+(end-start)/1000+"微秒"
- //三種遍歷,用entrySet()方法返回Set<Map.Entry<T,T>>型別,再獲取裡邊的Map.Entry
- start=System.nanoTime();
- Set<Map.Entry<String,String>> entrySet=mapTest.entrySet();
- for(Map.Entry<String, String> entry:entrySet){
- String key=entry.getKey();
- String value=entry.getValue();
- }
- end=System.nanoTime();
- System.out.println("entrySet遍歷map耗時"+(end-start)/1000+"微秒");
經過多次執行,結果大概都是這樣的:
- keySet遍歷map耗時9867微秒
- values遍歷map(只得到值)耗時2539微秒
- entrySet遍歷map耗時2783微秒
values()是返回Map的所有value的集合collection,只能遍歷到值,很難遍歷到key所以一般不用,除非在某種特殊場合,所以一般採用的第一種和第三種方式。而測試表明entrySet()方式遍歷效率更高。
entrySet()方式遍歷之所以快與keySet(),一個原因是keySet相當與遍歷了2次,一次是對key的Set集合的遍歷,二次是每次遍歷過程都要通過key和map.get(key)來獲取value值。第二個原因是map.get(key)獲取的時候,底層其實根據key的hashcode值經過雜湊演算法得到一個hash值然後作為索引對映到對應table陣列的索引位置,這是一次密集型計算,很耗費CPU,如果有大量的元素,則會使CPU使用率飆升,影響響應速度,而entrySet()返回的set裡邊元素都是Map.Entry型別,key和value就是這個類的一個屬性,entry.getKey()和entry.getValue()效率肯定很高。
所以平常開發過程中,如果對Map講究效率的遍歷的話,還是採用entrySet()方法。