java中遍历通过不同的元素遍历map的方式有3种:1.通过keySet遍历;2.通过entrySet遍历;3.获取values遍历value。通过不同的方式遍历又分为foreach和iterator。因为本文按照这几个维度,以不同数据量来分别测试所需时间。
主要测试方法如下:
private static void valuesIterator(Map<String, String> map) { /** values iterator遍历 */ long start = System.currentTimeMillis(); Iterator it = map.values().iterator(); while (it.hasNext()){ String value = (String)it.next(); } long end = System.currentTimeMillis(); System.out.println("values iterator遍历耗时:" + (end - start) + "ms"); } private static void valuesForeach(Map<String, String> map) { /** values foreach遍历 */ long start = System.currentTimeMillis(); for (String value : map.values()){ } long end = System.currentTimeMillis(); System.out.println("values foreach遍历耗时:"+(end-start)+"ms"); } private static void entryIterator(Map<String, String> map) { /** Map.Entry<K, V> iterator遍历 */ long start = System.currentTimeMillis(); Iterator it = map.entrySet().iterator(); while (it.hasNext()){ Map.Entry<String,String> entry = (Map.Entry<String,String>)it.next(); String key = entry.getKey(); String value = entry.getValue(); } long end = System.currentTimeMillis(); System.out.println("Map.Entry<K, V> iterator遍历耗时:"+(end-start)+"ms"); } private static void entryForeach(Map<String, String> map) { /** Map.Entry<K, V> foreach遍历 */ long start = System.currentTimeMillis(); for (Map.Entry<String,String> entry : map.entrySet()){ String key = entry.getKey(); String value = entry.getValue(); } long end = System.currentTimeMillis(); System.out.println("Map.Entry<K, V> foreach遍历耗时:" + (end - start) + "ms"); } private static void keySetIterator(Map<String, String> map) { /** keySet iterator遍历 */ long start = System.currentTimeMillis(); Iterator it = map.keySet().iterator(); while (it.hasNext()){ String key = (String)it.next(); String value = map.get(key); } long end = System.currentTimeMillis(); System.out.println("keySet iterator遍历耗时:"+(end-start)+"ms"); } private static void keySetForeach(Map<String, String> map) { /** keyset foreach遍历 */ long start = System.currentTimeMillis(); for (String key : map.keySet()){ String value = map.get(key); } long end = System.currentTimeMillis(); System.out.println("keyset foreach遍历耗时:"+(end-start)+"ms"); }
除此之外,还有一些类似的方法,这里就不都展示出来了。
private static void test(int n) { System.out.println(); System.out.println("-------------------------"); System.out.println(n+"条数据量测试:"); System.out.println(); Map<String,String> map = new HashMap(); for (int i = 0 ; i < n ; i++){ map.put(i+"aa",i+"ss"); } System.out.println("1.遍历key - value"); keySetForeach(map); keySetIterator(map); entryForeach(map); entryIterator(map); System.out.println(); System.out.println("2.遍历key"); keySetKeyForeach(map); keySetKeyIterator(map); entryKeyForeach(map); entryKeyIterator(map); System.out.println(); System.out.println("3.遍历value"); keySetValueForeach(map); keySetValueIterator(map); entryValueForeach(map); entryValueIterator(map); valuesForeach(map); valuesIterator(map); }
public static void main(String[] args) { test(50000); test(100000); test(1000000); }
这里通过3个数量级测试:5万条数据,10万条数据,100万条数据。
测试结果:
————————-
50000条数据量测试:
1.遍历key – value
keyset foreach遍历耗时:16ms
keySet iterator遍历耗时:13ms
Map.Entry<K, V> foreach遍历耗时:10ms
Map.Entry<K, V> iterator遍历耗时:11ms
2.遍历key
keyset foreach遍历耗时:8ms
keySet iterator遍历耗时:7ms
Map.Entry<K, V> foreach遍历耗时:9ms
Map.Entry<K, V> iterator遍历耗时:8ms
3.遍历value
keyset foreach遍历耗时:11ms
keySet iterator遍历耗时:12ms
Map.Entry<K, V> foreach遍历耗时:8ms
Map.Entry<K, V> iterator遍历耗时:7ms
values foreach遍历耗时:8ms
values iterator遍历耗时:8ms
————————-
100000条数据量测试:
1.遍历key – value
keyset foreach遍历耗时:13ms
keySet iterator遍历耗时:14ms
Map.Entry<K, V> foreach遍历耗时:10ms
Map.Entry<K, V> iterator遍历耗时:13ms
2.遍历key
keyset foreach遍历耗时:8ms
keySet iterator遍历耗时:8ms
Map.Entry<K, V> foreach遍历耗时:9ms
Map.Entry<K, V> iterator遍历耗时:10ms
3.遍历value
keyset foreach遍历耗时:13ms
keySet iterator遍历耗时:12ms
Map.Entry<K, V> foreach遍历耗时:9ms
Map.Entry<K, V> iterator遍历耗时:8ms
values foreach遍历耗时:8ms
values iterator遍历耗时:9ms
————————-
1000000条数据量测试:
1.遍历key – value
keyset foreach遍历耗时:66ms
keySet iterator遍历耗时:65ms
Map.Entry<K, V> foreach遍历耗时:47ms
Map.Entry<K, V> iterator遍历耗时:47ms
2.遍历key
keyset foreach遍历耗时:41ms
keySet iterator遍历耗时:41ms
Map.Entry<K, V> foreach遍历耗时:42ms
Map.Entry<K, V> iterator遍历耗时:42ms
3.遍历value
keyset foreach遍历耗时:66ms
keySet iterator遍历耗时:64ms
Map.Entry<K, V> foreach遍历耗时:43ms
Map.Entry<K, V> iterator遍历耗时:43ms
values foreach遍历耗时:42ms
values iterator遍历耗时:44ms
结果分析:
这里暂时不对key – value的复杂度、离散程度已经冲突进行测试,仅以简单的数字字符为主测试。
hashmap:
1.遍历key – value的时候,通常情况下,使用entrySet遍历比keySet更好,因为keySet要先拿到key,后查出value。
2.遍历key的时候,通常情况下,使用keySet遍历比entrySet更好,毕竟entrySet除了包含key之外还有value,需要更多的资源。
3.遍历value的时候,通常情况下,使用values最方便,其次entrySet。
4.遍历的方式推荐使用foreach循环,理由有二:1.性能稍好一些;2.代码简洁。
5.数据量越大,这种性能差异越明显。
treemap:
使用treemap测试,结论与hashmap一致,由于其查询特性决定,上述结论更加明显。