經常使用遍歷hashMap的方法對效率的影響

測試環境: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

根據實際狀況選擇吧。

 

 

歡迎各位補充。

相關文章
相關標籤/搜索