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

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

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

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

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

1.首先遍歷一個(gè)List

方式1.一開(kāi)始是這樣的:

public static void test1(List<String> list) {
 for (int i = 0; i < list.size(); i++) {
  System.out.println(list.get(i));
 }
}

方式2.當(dāng)然稍微高級(jí)一點(diǎn)的是這樣:

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.后來(lái)有了增強(qiáng)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);和下面的寫(xiě)法等價(jià)
 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)該沒(méi)有其他的了吧,上面六中方法,按我的使用習(xí)慣5最常用,4偶爾使用,其他的基本就不怎么用了,使用5的原因是因?yàn)榉奖銜?shū)寫(xiě),提示就可以寫(xiě)出來(lái),偶爾使用4的原因是,5不方便計(jì)數(shù)用,下面進(jìn)行性能測(cè)試,String不具備代表性,決定使用對(duì)象,簡(jiǎn)單的一個(gè)測(cè)試類如下:

  一個(gè)簡(jiǎn)單的測(cè)試,內(nèi)容不要太在意,簡(jiǎn)單計(jì)算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);和下面的寫(xiě)法等價(jià)
 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 + "]";
 }
}

  運(yùn)行三次取平均值,機(jī)器配置就不說(shuō)了,因?yàn)槲也皇潜容^的絕對(duì)值,我是比較的這幾種方式的相對(duì)值,數(shù)據(jù)結(jié)果,趨勢(shì)圖如下:

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

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

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

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

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

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

2.再次遍歷一個(gè)Set

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

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)過(guò)計(jì)算得出如下結(jié)果:

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

3.最后遍歷Map

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

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ù)眾望,最快的是增強(qiáng)for循環(huán)。

最終結(jié)論

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

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

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

相關(guān)文章

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

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

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

    詳解Java適配器模式

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

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

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

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

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

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

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

    Spring?Boot?條件注解詳情

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

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

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

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

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

    mybatis中的緩存機(jī)制

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

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

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

最新評(píng)論