欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入了解java8的foreach循環(huán)

 更新時間:2017年05月30日 11:04:39   作者:已往之不諫  
雖然java8出來很久了,但是之前用的一直也不多,最近正好學(xué)習(xí)了java8。下面給大家分享java8中的foreach循環(huán),感興趣的朋友一起看看吧

雖然java8出來很久了,但是之前用的一直也不多,最近正好學(xué)習(xí)了java8,推薦一本書還是不錯的<寫給大忙人看的javase8>。因為學(xué)習(xí)了Java8,所以只要能用到的地方都會去用,尤其是Java8的Stream,感覺用起來覺得很方便,因為點點點就出來了,而且代碼那么簡潔?,F(xiàn)在開始慢慢深入了解java8,發(fā)現(xiàn)很多東西不能看表面。

  比如常規(guī)遍歷一個集合,下面給出例子:

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.當(dāng)然稍微高級一點的是這樣:

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循環(huán):

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);
 });
}

  應(yīng)該沒有其他的了吧,上面六中方法,按我的使用習(xí)慣5最常用,4偶爾使用,其他的基本就不怎么用了,使用5的原因是因為方便書寫,提示就可以寫出來,偶爾使用4的原因是,5不方便計數(shù)用,下面進(jìn)行性能測試,String不具備代表性,決定使用對象,簡單的一個測試類如下:

  一個簡單的測試,內(nèi)容不要太在意,簡單計算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 + ", name=" + name + "]";
 }
}

  運行三次取平均值,機(jī)器配置就不說了,因為我不是比較的絕對值,我是比較的這幾種方式的相對值,數(shù)據(jù)結(jié)果,趨勢圖如下:

  然后去掉表現(xiàn)一直很穩(wěn)定的方式5和百萬級數(shù)據(jù)量以上的數(shù)據(jù),來分析結(jié)果:

  可以得出一個非常嚇人的結(jié)果,java8的foreach每次循環(huán)的耗時竟然高達(dá)100毫秒以上,雖然它比較穩(wěn)定(算是優(yōu)點吧)。所以得出以下結(jié)論:

  在正常使用(數(shù)據(jù)量少于百萬以下),正常(非并行)遍歷一個集合的時候:

•不要使用java8的foreach,每次耗時高達(dá)100毫秒以上

•提前計算出大小的普通for循環(huán),耗時最小,但是書寫麻煩

•增強for循環(huán)表現(xiàn)良好

2.再次遍歷一個Set

  使用以相同的方式測試HashSet,測試方法如下:

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();
  });
 }
}

  經(jīng)過計算得出如下結(jié)果:

  不難發(fā)現(xiàn),java8的foreach依然每次耗時100ms以上,最快的變成了增強for循環(huán),Iterator遍歷和java8的iterator().forEachRemaining差不多。

3.最后遍歷Map

  依然使用相同的方式測試Map集合遍歷,測試類如下:

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();
  });
 }
}

  結(jié)果如下:

  java8的foreach依然不負(fù)眾望,最快的是增強for循環(huán)。

最終結(jié)論

    普通(數(shù)量級10W以下,非并行)遍歷一個集合(List、Set、Map)如果在意效率,不要使用java8的foreach,雖然它很方便很優(yōu)雅

    任何時候使用增強for循環(huán)是你不二的選擇

以上所述是小編給大家介紹的java8的foreach循環(huán) ,希望對大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會及時回復(fù)大家的!

相關(guān)文章

  • 淺談spring的重試機(jī)制無效@Retryable@EnableRetry

    淺談spring的重試機(jī)制無效@Retryable@EnableRetry

    這篇文章主要介紹了淺談spring的重試機(jī)制無效@Retryable@EnableRetry,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • 詳解Java適配器模式

    詳解Java適配器模式

    這篇文章主要介紹了Java適配器模式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • Java計算一個數(shù)加上100是完全平方數(shù),加上168還是完全平方數(shù)

    Java計算一個數(shù)加上100是完全平方數(shù),加上168還是完全平方數(shù)

    這篇文章主要介紹了Java計算一個數(shù)加上100是完全平方數(shù),加上168還是完全平方數(shù),需要的朋友可以參考下
    2017-02-02
  • Spring boot + LayIM + t-io 實現(xiàn)文件上傳、 監(jiān)聽用戶狀態(tài)的實例代碼

    Spring boot + LayIM + t-io 實現(xiàn)文件上傳、 監(jiān)聽用戶狀態(tài)的實例代碼

    這篇文章主要介紹了Spring boot + LayIM + t-io 實現(xiàn)文件上傳、 監(jiān)聽用戶狀態(tài)的實例代碼,需要的朋友可以參考下
    2017-12-12
  • Java線程池中的各個參數(shù)如何合理設(shè)置

    Java線程池中的各個參數(shù)如何合理設(shè)置

    這篇文章主要介紹了Java線程池中的各個參數(shù)如何合理設(shè)置操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Spring?Boot?條件注解詳情

    Spring?Boot?條件注解詳情

    這篇文章主要介紹了Spring?Boot?條件注解詳情,SpringBoot條件注解@Conditional,可用于根據(jù)某個特定的條件來判斷是否需要創(chuàng)建某個特定的Bean,下文更多相關(guān)介紹,需要的小伙伴可以參考一下
    2022-05-05
  • java 實現(xiàn)線程同步的方式有哪些

    java 實現(xiàn)線程同步的方式有哪些

    當(dāng)使用多個線程來訪問同一個數(shù)據(jù)時,非常容易出現(xiàn)線程安全問題,所以我們用同步機(jī)制來解決這些問題,本文將詳細(xì)介紹,需要的朋友可以參考下
    2012-11-11
  • SpringBoot+Vue+JWT的前后端分離登錄認(rèn)證詳細(xì)步驟

    SpringBoot+Vue+JWT的前后端分離登錄認(rèn)證詳細(xì)步驟

    這篇文章主要介紹了SpringBoot+Vue+JWT的前后端分離登錄認(rèn)證,其實創(chuàng)建后端springboot工程也很簡單,本文安裝idea步驟一步步給大家詳細(xì)介紹,需要的朋友可以參考下
    2021-09-09
  • mybatis中的緩存機(jī)制

    mybatis中的緩存機(jī)制

    這篇文章主要介紹了mybatis中的緩存機(jī)制用法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • java基礎(chǔ)學(xué)習(xí)筆記之泛型

    java基礎(chǔ)學(xué)習(xí)筆記之泛型

    所謂泛型,就是變量類型的參數(shù)化。泛型是JDK1.5中一個最重要的特征。通過引入泛型,我們將獲得編譯時類型的安全和運行時更小的拋出ClassCastException的可能。在JDK1.5中,你可以聲明一個集合將接收/返回的對象的類型。
    2016-02-02

最新評論