当前位置: 首页 > 科技观察

Java中九种Map遍历方法

时间:2023-03-14 15:15:35 科技观察

Map绝对是我们Java程序员在日常工作中经常用到的一种数据结构,从最早的Iterator,到java5支持的foreach,再到java8的Lambda,你经常用到的是哪一个它?遍历entrySet1.遍历for和map.entrySet()第一种方式是以for和Map.Entry的形式进行遍历,通过遍历map.entrySet()得到每个entry的key和value。代码如下。这种方法一般阿芬用的比较多。没有花哨的用法,但是获取map的key和value非常简单。publicstaticvoidtestMap1(Mapmap){  longsum=0;  for(Map.Entryentry:map.entrySet()){  sum+=entry.getKey()+entry.getValue();  }  System.out.println(sum);  }看过HashMap源码的同学应该会发现源码中也用到了这种遍历方式,如图下面,putMapEntries方法在我们调用putAll方法时会用到。2.遍历for、Iterator和map.entrySet()我们第一种方法是直接遍历for和entrySet(),这次我们使用entrySet()的迭代器来遍历,代码如下。publicstaticvoidtestMap2(Mapmap){  longsum=0;  for(Iterator>entries=map.entrySet().iterator();entries.hasNext();){  Map.Entryentry=entries.next();  sum+=entry.getKey()+entry.getValue();  }  System.out.println(sum);  }3。通过while、Iterator和map.entrySet()遍历上面的iterator是使用for来遍历的,那么我们自然而然的就会想到while遍历,所以代码如下。publicstaticvoidtestMap3(Mapmap){  Iterator>it=map.entrySet().iterator();  longsum=0;  while(it.hasNext()){  Map.Entryentry=it.next();  sum+=entry.getKey()+entry.getValue();  }  System.out.println(sum);  }这个方法和上面的方法类似,只是循环由for改为while。在日常开发中,for和while在很多场景下是可以替换的。2和3都使用了迭代器Iterator,通过迭代器的next()方法获取下一个对象,然后判断是否有next。通过keySet遍历以上三种方法虽然代码写的不一样,但是都是通过遍历map.entrySet()得到结果,而且都是一个目标。接下来我们看另一组。4.遍历for和map.keySet()前面的遍历是通过map.entrySet()。这里我们遍历map.keySet()。顾名思义,前者是条目的集合,后者是键的集合。Collection,遍历代码如下,因为是key的集合,所以想要获取key对应的value,需要通过map.get(key)获取。publicstaticvoidtestMap4(Mapmap){  longsum=0;  for(Integerkey:map.keySet()){  sum+=key+map.get(key);  }  System.out.println(sum);  }5.通过for、Iterator和map.keySet()遍历publicstaticvoidtestMap5(Mapmap){  longsum=0;  for(Iteratorkey=map.keySet().iterator();key.hasNext();){  整数k=key.next();  sum+=k+map.get(k);  }  System.out.println(sum);  }6.通过while、Iterator和map.keySet()遍历publicstaticvoidtestMap6(Mapmap){  Iteratorit=map.keySet().iterator();  longsum=0;  while(it.hasNext()){  Integerkey=it.next();  sum+=key+map.get(key);  }  系统。out.println(sum);  }我们可以看到,这个方法比map.entrySet()方法多了一个get操作。这种场景比较适合我们只需要key的场景。如果我们还需要使用value的场景,不建议使用map.keySet()进行遍历,因为会多一次map.get()操作。Java8的遍历方法注意以下遍历方法都是JDK1.8引入的。如果使用的JDK版本不是1.8或更高版本,则不支持。7、使用map.forEach()遍历JDK中的forEach方法,使用率相当高。publicstaticvoidtestMap7(Mapmap){  finallong[]sum={0};  map.forEach((key,value)->{  sum[0]+=key+value;  });  System.out.println(sum[0]);  }该方法定义在java.util.Map#forEach中,通过default关键字标识,如下图所示。8.Stream遍历publicstaticvoidtestMap8(Mapmap){  longsum=map.entrySet().stream().mapToLong(e->e.getKey()+e.getValue()).sum();  System.out.println(sum);  }9.ParallelStream遍历publicstaticvoidtestMap9(Mapmap){  longsum=map.entrySet().parallelStream().mapToLong(e->e.getKey()+e.getValue()).sum();  System.out.println(sum);}这两种遍历方式是JDK8的Stream遍历方式,stream是普通的遍历方式,parallelStream是并行流遍历,在某些场景下会提升性能,但不一定。测试代码上面的遍历方法,我们在日常开发中应该使用哪一种呢?各自的表现如何?为此,阿芬使用如下代码来测试各个方法的执行时间。publicstaticvoidmain(String[]args){  intoutSize=1;  intmapSize=200;  Mapmap=newHashMap<>(mapSize);  for(inti=0;i0;size--){  longstartTime=System.当前时间毫秒();  testMap1(map);  totalTime+=System.currentTimeMillis()-startTime;  }  System.out.println("testMap1avgtimeis:"+(totalTime/outSize));  //省略其他方法,代码同上  }为了避免一些干扰,这里使用外层for进行多次计算,然后计算平均值。当我们的参数为outSize=1和mapSize=200时,测试结果如下。当我们增加mapSize时,我们会发现后一种方法的性能逐渐提高。小结从上面的例子来看,当我们的集合数量比较少的时候,基本上可以进行普通的遍历,不需要使用JDK8的高级API进行遍历。当我们的集合数量很多的时候,就可以考虑使用JDK8的forEach或者Stream来进行遍历,效率更高。entrySet()方法在普通遍历方法中优于keySet()方法。