雖然java8出來很久了,但是之前用的一直也不多,最近正好學習了java8,推薦一本書還是不錯的<寫給大忙人看的javase8>。因為學習了java8,所以只要能用到的地方都會去用,尤其是java8的stream,感覺用起來覺得很方便,因為點點點就出來了,而且代碼那么簡潔。現在開始慢慢深入了解java8,發(fā)現很多東西不能看表面。
比如常規(guī)遍歷一個集合,下面給出例子:
1.首先遍歷一個list
方式1.一開始是這樣的:
1
2
3
4
5
|
public static void test1(list<string> list) { for ( int i = 0 ; i < list.size(); i++) { system.out.println(list.get(i)); } } |
方式2.當然稍微高級一點的是這樣:
1
2
3
4
5
|
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遍歷:
1
2
3
4
5
6
|
public static void test3(list<string> list) { iterator<string> iterator = list.iterator(); while (iterator.hasnext()){ system.out.println(iterator.next()); } } |
方式4.后來有了增強for循環(huán):
1
2
3
4
5
|
public static void test4(list<string> list) { for (string str:list){ system.out.println(str); } } |
方式5.java8以后新增的方式:
1
2
3
4
5
6
|
public static void test5(list<string> list) { //list.foreach(system.out::println);和下面的寫法等價 list.foreach(str->{ system.out.println(str); }); } |
方式6.還有另一種:
1
2
3
4
5
|
public static void test6(list<string> list) { list.iterator().foreachremaining(str->{ system.out.println(str); }); } |
應該沒有其他的了吧,上面六中方法,按我的使用習慣5最常用,4偶爾使用,其他的基本就不怎么用了,使用5的原因是因為方便書寫,提示就可以寫出來,偶爾使用4的原因是,5不方便計數用,下面進行性能測試,string不具備代表性,決定使用對象,簡單的一個測試類如下:
一個簡單的測試,內容不要太在意,簡單計算hashcode:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
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 + ", name=" + name + "]" ; } } |
運行三次取平均值,機器配置就不說了,因為我不是比較的絕對值,我是比較的這幾種方式的相對值,數據結果,趨勢圖如下:
然后去掉表現一直很穩(wěn)定的方式5和百萬級數據量以上的數據,來分析結果:
可以得出一個非常嚇人的結果,java8的foreach每次循環(huán)的耗時竟然高達100毫秒以上,雖然它比較穩(wěn)定(算是優(yōu)點吧)。所以得出以下結論:
在正常使用(數據量少于百萬以下),正常(非并行)遍歷一個集合的時候:
•不要使用java8的foreach,每次耗時高達100毫秒以上
•提前計算出大小的普通for循環(huán),耗時最小,但是書寫麻煩
•增強for循環(huán)表現良好
2.再次遍歷一個set
使用以相同的方式測試hashset,測試方法如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
package test; import java.util.hashset; import java.util.iterator; import java.util.set; public class test9 { public static void main(string[] args) { set<dog> set = new hashset<>(); for ( int i = 0 ; i < 10_000_000; i++) { set.add( new dog(i, "dog" + i)); } long nanotime = system.nanotime(); test1(set); long nanotime1 = system.nanotime(); test2(set); long nanotime2 = system.nanotime(); test3(set); long nanotime3 = system.nanotime(); test4(set); long nanotime4 = 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 ); } public static void test1(set<dog> list) { iterator<dog> iterator = list.iterator(); while (iterator.hasnext()) { iterator.next().hashcode(); } } public static void test2(set<dog> list) { for (dog dog : list) { dog.hashcode(); } } public static void test3(set<dog> list) { list.foreach(dog -> { dog.hashcode(); }); } public static void test4(set<dog> list) { list.iterator().foreachremaining(dog -> { dog.hashcode(); }); } } |
經過計算得出如下結果:
不難發(fā)現,java8的foreach依然每次耗時100ms以上,最快的變成了增強for循環(huán),iterator遍歷和java8的iterator().foreachremaining差不多。
3.最后遍歷map
依然使用相同的方式測試map集合遍歷,測試類如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
package test; import java.util.hashmap; import java.util.iterator; import java.util.map; import java.util.set; public class test10 { public static void main(string[] args) { map<string, dog> map = new hashmap<>(); for ( int i = 0 ; i < 1000_000; i++) { map.put( "dog" + i, new dog(i, "dog" + i)); } long nanotime = system.nanotime(); test1(map); long nanotime1 = system.nanotime(); test2(map); long nanotime2 = system.nanotime(); test3(map); long nanotime3 = system.nanotime(); test4(map); long nanotime4 = 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 ); } public static void test1(map<string, dog> map) { iterator<map.entry<string, dog>> entries = map.entryset().iterator(); while (entries.hasnext()) { map.entry<string, dog> entry = entries.next(); int code=entry.getkey().hashcode()+entry.getvalue().hashcode(); } } public static void test2(map<string, dog> map) { for (map.entry<string, dog> entry : map.entryset()) { int code=entry.getkey().hashcode()+entry.getvalue().hashcode(); } } public static void test3(map<string, dog> map) { for (string key : map.keyset()) { int code=key.hashcode()+map.get(key).hashcode(); } } public static void test4(map<string, dog> map) { map.foreach((key, value) -> { int code=key.hashcode()+value.hashcode(); }); } } |
結果如下:
java8的foreach依然不負眾望,最快的是增強for循環(huán)。
最終結論
普通(數量級10w以下,非并行)遍歷一個集合(list、set、map)如果在意效率,不要使用java8的foreach,雖然它很方便很優(yōu)雅
任何時候使用增強for循環(huán)是你不二的選擇
以上所述是小編給大家介紹的java8的foreach循環(huán) ,希望對大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會及時回復大家的!
原文鏈接:http://www.cnblogs.com/yiwangzhibujian/p/6919435.html