虽然Java8出来很久了,但是之前用的一直也不多,最近正好学习了Java8,推荐一本书还是不错的<写给大忙人看的javase8>。因为学习了Java8,所以只要能用到的地方都会去用,尤其是Java8的Stream,感觉用起来觉得很方便,因为点点点就出来了,而且代码那么简洁。现在开始慢慢深入了解Java8,发现很多东西不能看表面。
比如常规遍历一个集合,下面给出例子:
1.首先遍历一个List方式1.一开始是这样的:
public static void test1(List<String> list) { for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); } }
方式2.当然稍微高级一点的是这样:
public static void test2(List<String> list) { for (int i = 0,lengh=list.size(); i < lengh; i++) { System.out.println(list.get(i)); } }
方式3.还有就是Iterator遍历:
public static void test3(List<String> list) { Iterator<String> iterator = list.iterator(); while(iterator.hasNext()){ System.out.println(iterator.next()); } }
方式4.后来有了增强for循环:
public static void test4(List<String> list) { for(String str:list){ System.out.println(str); } }
方式5.java8以后新增的方式:
public static void test5(List<String> list) { //list.forEach(System.out::println);和下面的写法等价 list.forEach(str->{ System.out.println(str); }); }
方式6.还有另一种:
public static void test6(List<String> list) { list.iterator().forEachRemaining(str->{ System.out.println(str); }); }
应该没有其他的了吧,上面六中方法,按我的使用习惯5最常用,4偶尔使用,其他的基本就不怎么用了,使用5的原因是因为方便书写,提示就可以写出来,偶尔使用4的原因是,5不方便计数用,下面进行性能测试,String不具备代表性,决定使用对象,简单的一个测试类如下:
一个简单的测试,内容不要太在意,简单计算hashCode:
package test; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class Test8 { public static void main(String[] args) { List<Dog> list=new ArrayList<>(); for(int i=0;i<10;i++){ list.add(new Dog(i,"dog"+i)); } long nanoTime = System.nanoTime(); test1(list); long nanoTime1 = System.nanoTime(); test2(list); long nanoTime2 = System.nanoTime(); test3(list); long nanoTime3 = System.nanoTime(); test4(list); long nanoTime4 = System.nanoTime(); test5(list); long nanoTime5 = System.nanoTime(); test6(list); long nanoTime6 = System.nanoTime(); System.out.println((nanoTime1-nanoTime)/1000000.0); System.out.println((nanoTime2-nanoTime1)/1000000.0); System.out.println((nanoTime3-nanoTime2)/1000000.0); System.out.println((nanoTime4-nanoTime3)/1000000.0); System.out.println((nanoTime5-nanoTime4)/1000000.0); System.out.println((nanoTime6-nanoTime5)/1000000.0); } public static void test1(List<Dog> list) { for (int i = 0; i < list.size(); i++) { list.get(i).hashCode(); } } public static void test2(List<Dog> list) { for (int i = 0,lengh=list.size(); i < lengh; i++) { list.get(i).hashCode(); } } public static void test3(List<Dog> list) { Iterator<Dog> iterator = list.iterator(); while(iterator.hasNext()){ iterator.next().hashCode(); } } public static void test4(List<Dog> list) { for(Dog dog:list){ dog.hashCode(); } } public static void test5(List<Dog> list) { //list.forEach(System.out::println);和下面的写法等价 list.forEach(dog->{ dog.hashCode(); }); } public static void test6(List<Dog> list) { list.iterator().forEachRemaining(dog->{ dog.hashCode(); }); } } class Dog{ private int age; private String name; public Dog(int age, String name) { super(); this.age = age; this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Dog [age=" + age + ",]"; } } View Code
运行三次取平均值,机器配置就不说了,因为我不是比较的绝对值,我是比较的这几种方式的相对值,数据结果,趋势图如下:
然后去掉表现一直很稳定的方式5和百万级数据量以上的数据,来分析结果:
可以得出一个非常吓人的结果,java8的foreach每次循环的耗时竟然高达100毫秒以上,虽然它比较稳定(算是优点吧)。所以得出以下结论:
在正常使用(数据量少于百万以下),正常(非并行)遍历一个集合的时候:
不要使用java8的foreach,每次耗时高达100毫秒以上
提前计算出大小的普通for循环,耗时最小,但是书写麻烦
增强for循环表现良好
2.再次遍历一个Set使用以相同的方式测试HashSet,测试方法如下: