HashMap为例子:
public static void main(String[] args) {
//初始化map结构
HashMap<Integer,String> map= new HashMap<Integer,String>();
for(int i = 0;i < 10;i++){
map.put(i, "第"+i+"个元素");
}
//第一种方式:keySet的增强for循环遍历方式
long time1 = System.nanoTime();
for(Integer key : map.keySet()){
map.get(key);
}
long time2 = System.nanoTime();
//第二种方式:keySet的Iterator遍历方式
Iterator<Integer> iterator = map.keySet().iterator();
while(iterator.hasNext()){
Integer key = iterator.next();
map.get(key);
}
long time3 = System.nanoTime();
//第三种方式:entrySet的增强for循环遍历方式
for(Map.Entry<Integer,String> entry: map.entrySet()){
entry.getKey();
entry.getValue();
}
long time4 = System.nanoTime();
//第四种方式:entrySet的Iterator遍历方式
Iterator<Map.Entry<Integer, String>> iterator2 = map.entrySet().iterator();
Map.Entry<Integer, String> entry;
while(iterator2.hasNext()){
entry = iterator2.next();
entry.getKey();
entry.getValue();
}
long time5 = System.nanoTime();
//第五种方式:values的增强for循环遍历方式
//values()方法的for循环遍历方式
Collection<String> values = map.values();
for(String value : values){
}
long time6 = System.nanoTime();
//第六种方式:values的Iterator遍历方式
Iterator<String> iterator3 = map.values().iterator();
String value;
while(iterator3.hasNext()){
value=iterator3.next();
}
long time7 = System.nanoTime();
//第七种方式:JDK 1.8支持的Lambda表达式
map.forEach((key, value2) -> {
});
long time8 = System.nanoTime();
//第七种方式:JDK 1.8支持的Lambda表达式(第二遍)
map.forEach((key, value2) -> {
});
long time9 = System.nanoTime();
System.out.println("第一种方式:keySet的增强for循环遍历方式:" + (time2-time1)/1000 + "微秒");
System.out.println("第二种方式:keySet的Iterator遍历方式:" + (time3-time2)/1000 + "微秒");
System.out.println("第三种方式:entrySet的增强for循环遍历方式:" + (time4-time3)/1000 + "微秒");
System.out.println("第四种方式:entrySet的Iterator遍历方式:" + (time5-time4)/1000 + "微秒");
System.out.println("第五种方式:values的增强for循环遍历方式:" + (time6-time5)/1000 + "微秒");
System.out.println("第六种方式:values的Iterator遍历方式:" + (time7-time6)/1000 + "微秒");
System.out.println("第七种方式:JDK 1.8支持的Lambda表达式:" + (time8-time7)/1000 + "微秒");
System.out.println("第七种方式:JDK 1.8支持的Lambda表达式(第二遍)" + (time9-time8)/1000 + "微秒");
}
数据量为10 的结果:
第一种方式:keySet的增强for循环遍历方式:187微秒
第二种方式:keySet的Iterator遍历方式:2微秒
第三种方式:entrySet的增强for循环遍历方式:18微秒
第四种方式:entrySet的Iterator遍历方式:2微秒
第五种方式:values的增强for循环遍历方式:170微秒
第六种方式:values的Iterator遍历方式:1微秒
第七种方式:JDK 1.8支持的Lambda表达式:33128微秒
第七种方式:JDK 1.8支持的Lambda表达式(第二遍)181微秒
数据量为1万的结果:
第一种方式:keySet的增强for循环遍历方式:1211微秒
第二种方式:keySet的Iterator遍历方式:625微秒
第三种方式:entrySet的增强for循环遍历方式:695微秒
第四种方式:entrySet的Iterator遍历方式:614微秒
第五种方式:values的增强for循环遍历方式:602微秒
第六种方式:values的Iterator遍历方式:384微秒
第七种方式:JDK 1.8支持的Lambda表达式:35414微秒
第七种方式:JDK 1.8支持的Lambda表达式(第二遍)721微秒
数据量为10万的结果:
第一种方式:keySet的增强for循环遍历方式:5696微秒
第二种方式:keySet的Iterator遍历方式:3887微秒
第三种方式:entrySet的增强for循环遍历方式:3402微秒
第四种方式:entrySet的Iterator遍历方式:2634微秒
第五种方式:values的增强for循环遍历方式:2425微秒
第六种方式:values的Iterator遍历方式:1917微秒
第七种方式:JDK 1.8支持的Lambda表达式:39311微秒
第七种方式:JDK 1.8支持的Lambda表达式(第二遍)4305微秒
总结:
entrySet的方式比keySet性能要好,原因在于keySet相当于遍历了2次,一次是对key的Set集合的遍历,二次是每次遍历过程都要通过key和map.get(key)来获取value值。map.get(key)的时候,底层是根据key的hashCode值经过哈希算法得到一个hash值,然后作为索引映射到对应的table数组的索引位置,这是一次密集型计算,很耗费CPU,如果有大量的元素,则会使CPU使用率飙升,影响响应速度,而entrySet()返回的set里面的元素都是Map.Enpty类型,key和value就是这个类的一个属性,entry.getKey()和entry.getValue()效率肯定很高。
values的方式,Map的所有value的集合的Collection,只能遍历到value,很难遍历到key,所以一般不用,如果当我们只需要取得value值时,采用values来遍历效率更高。
从上面的几种方式的for循环遍历和Iterator遍历的方式耗时结果来看,Iterator遍历的效率会比for循环效率更快一点。
lambda表达式的方式,第一次特别的慢,之后的效率有显著提升,建议初始化放到项目启动的过程中,这样可以大大提高lambda表达式的性能。