最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java遍歷機(jī)制性能的比較詳解

 更新時(shí)間:2019年06月10日 09:36:07   作者:cartoony  
這篇文章主要給大家介紹了關(guān)于java遍歷機(jī)制性能比較的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧

緣由

近段時(shí)間在寫leetcode的Lemonade Change時(shí)候,發(fā)現(xiàn)了for循環(huán)與forEach循環(huán)的耗時(shí)是不一致的,在提交記錄上面差了一倍......

平常開發(fā)絕大部分業(yè)務(wù)邏輯的實(shí)現(xiàn)都需要遍歷機(jī)制的幫忙,雖說也有注意到各數(shù)據(jù)結(jié)構(gòu)操作的性能比較,但是忽視了遍歷機(jī)制性能的差異。原本前兩天就開始動(dòng)手寫,拖延癥......

正文

現(xiàn)階段我所知道JAVA遍歷機(jī)制有三種

  • for循環(huán)
  • forEach循環(huán)
  • Iterator循環(huán)

JAVA數(shù)據(jù)結(jié)構(gòu)千千萬(wàn),但是大部分都是對(duì)基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)的封裝,比較HashMap依賴于Node數(shù)組,LinkedList底層是鏈表,ArrayList對(duì)數(shù)組的再封裝......扯遠(yuǎn)了

總結(jié)來說,JAVA的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu),我覺得有兩種

  • 數(shù)組
  • 鏈表

如果是加上Hash(Hash的操作與數(shù)組以及鏈表不太一致),就是三種

因?yàn)槠匠i_發(fā)大部分都優(yōu)先選擇包裝后的數(shù)據(jù)結(jié)構(gòu),所以下面我會(huì)使用

  • ArrayList(包裝后的數(shù)組)
  • LinkedList(包裝后的鏈表)
  • HashSet(包裝后的Hash類型數(shù)組)

這三種數(shù)據(jù)結(jié)構(gòu)在遍歷機(jī)制不同的時(shí)候時(shí)間的差異

可能有人對(duì)我為什么不對(duì)比HashMap呢,因?yàn)镴AVA設(shè)計(jì)中,是先實(shí)現(xiàn)了Map,再實(shí)現(xiàn)Set。如果你有閱讀過源碼就會(huì)發(fā)現(xiàn):每個(gè)Set子類的實(shí)現(xiàn)中,都有一個(gè)序列化后的Map對(duì)應(yīng)屬性實(shí)現(xiàn),而因?yàn)镠ash的查找時(shí)間復(fù)雜度為O(1),得出key后查找value的時(shí)間大致是一致的,所以我不對(duì)比HashMap。

題外話

我在閱讀《瘋狂JAVA》讀到:JAVA的設(shè)計(jì)者將Map的內(nèi)部entry數(shù)組中的value設(shè)為null進(jìn)而實(shí)現(xiàn)了Set。因?yàn)槲沂且栽创a以及官方文檔為準(zhǔn),具體我不清楚正確與否,但是因?yàn)镠ash中的key互不相同,Set中元素也互不相同,所以我認(rèn)為這個(gè)觀點(diǎn)是正確的。

為了測(cè)試的公平性,我會(huì)采取以下的限定

每種數(shù)據(jù)結(jié)構(gòu)的大小都設(shè)置三種量級(jí)

  • 10
  • 100
  • 1000

元素都采用隨機(jī)數(shù)生成

遍歷進(jìn)行操作都為輸出當(dāng)前元素的值

注:時(shí)間開銷受本地環(huán)境的影響,可能測(cè)量值會(huì)出現(xiàn)變化,但是總體上比例是正確的

ArrayList的比較

代碼

public class TextArray {

  private static Random random;

  private static List<Integer> list1;

  private static List<Integer> list2;

  private static List<Integer> list3;

  public static void execute(){
    random=new Random();
    initArray();
    testForWith10Object();
    testForEachWith10Object();
    testIteratorWith10Object();
    testForWith100Object();
    testForEachWith100Object();
    testIteratorWith100Object();
    testForWith1000Object();
    testForEachWith1000Object();
    testIteratorWith1000Object();
  }

  private static void testForWith10Object(){
    printFor(list1);
  }

  private static void testForWith100Object(){
    printFor(list2);
  }

  private static void testForWith1000Object(){
    printFor(list3);
  }

  private static void testForEachWith10Object(){
    printForeach(list1);
  }

  private static void testForEachWith100Object(){
    printForeach(list2);
  }

  private static void testForEachWith1000Object(){
    printForeach(list3);
  }

  private static void testIteratorWith10Object() {
    printIterator(list1);
  }

  private static void testIteratorWith100Object() {
    printIterator(list2);
  }

  private static void testIteratorWith1000Object() {
    printIterator(list3);
  }

  private static void printFor(List<Integer> list){
    System.out.println();
    System.out.print("data:");
    long start=System.currentTimeMillis();
    for(int i=0,length=list.size();i<length;i++){
      System.out.print(list.get(i)+" ");
    }
    System.out.println();
    long end=System.currentTimeMillis();
    System.out.println("for for "+list.size()+":"+(end-start)+"ms");
  }

  private static void printForeach(List<Integer> list){
    System.out.println();
    System.out.print("data:");
    long start=System.currentTimeMillis();
    for(int temp:list){
      System.out.print(temp+" ");
    }
    System.out.println();
    long end=System.currentTimeMillis();
    System.out.println("foreach for "+list.size()+":"+(end-start)+"ms");
  }

  private static void printIterator(List<Integer> list){
    System.out.println();
    System.out.print("data:");
    Iterator<Integer> it=list.iterator();
    long start=System.currentTimeMillis();
    while(it.hasNext()){
      System.out.print(it.next()+" ");
    }
    System.out.println();
    long end=System.currentTimeMillis();
    System.out.println("iterator for "+list.size()+":"+(end-start)+"ms");
  }

  private static void initArray(){
    list1=new ArrayList<>();
    list2=new ArrayList<>();
    list3=new ArrayList<>();
    for(int i=0;i<10;i++){
      list1.add(random.nextInt());
    }
    for(int i=0;i<100;i++){
      list2.add(random.nextInt());
    }
    for(int i=0;i<1000;i++){
      list3.add(random.nextInt());
    }
  }
}

輸出(忽略對(duì)元素的輸出)

for for 10:1ms
foreach for 10:0ms
iterator for 10:2ms

for for 100:5ms
foreach for 100:4ms
iterator for 100:12ms

for for 1000:33ms
foreach for 1000:7ms
iterator for 1000:16ms

10 100 1000
for 1ms 5ms 33ms
forEach 0ms 4ms 7ms
Iterator 2ms 12ms 16ms

結(jié)論

    for的性能最不穩(wěn)定,foreach次之,Iterator最好

使用建議

  • 在數(shù)據(jù)量不明確的情況下(可能1w,10w或其他),建議使用Iterator進(jìn)行遍歷
  • 在數(shù)據(jù)量明確且量級(jí)小的時(shí)候,優(yōu)先使用foreach
  • 需要使用索引時(shí),使用遞增變量的開銷比f(wàn)or的要小

LinkedList的比較

代碼

public class TextLinkedList {

  private static Random random;

  private static List<Integer> list1;

  private static List<Integer> list2;

  private static List<Integer> list3;

  public static void execute(){
    random=new Random();
    initList();
    testForWith10Object();
    testForEachWith10Object();
    testIteratorWith10Object();
    testForWith100Object();
    testForEachWith100Object();
    testIteratorWith100Object();
    testForWith1000Object();
    testForEachWith1000Object();
    testIteratorWith1000Object();
  }

  private static void testForWith10Object() {
    printFor(list1);
  }

  private static void testForEachWith10Object() {
    printForeach(list1);
  }

  private static void testIteratorWith10Object() {
    printIterator(list1);
  }

  private static void testForWith100Object() {
    printFor(list2);
  }

  private static void testForEachWith100Object() {
    printForeach(list2);
  }

  private static void testIteratorWith100Object() {
    printIterator(list2);
  }

  private static void testForWith1000Object() {
    printFor(list3);
  }

  private static void testForEachWith1000Object() {
    printForeach(list3);
  }

  private static void testIteratorWith1000Object() {
    printIterator(list3);
  }

  private static void printFor(List<Integer> list){
    System.out.println();
    System.out.print("data:");
    long start=System.currentTimeMillis();
    for(int i=0,size=list.size();i<size;i++){
      System.out.print(list.get(i));
    }
    System.out.println();
    long end=System.currentTimeMillis();
    System.out.println("for for "+list.size()+":"+(end-start)+"ms");
  }

  private static void printForeach(List<Integer> list){
    System.out.println();
    System.out.print("data:");
    long start=System.currentTimeMillis();
    for(int temp:list){
      System.out.print(temp+" ");
    }
    System.out.println();
    long end=System.currentTimeMillis();
    System.out.println("foreach for "+list.size()+":"+(end-start)+"ms");
  }

  private static void printIterator(List<Integer> list){
    System.out.println();
    System.out.print("data:");
    Iterator<Integer> it=list.iterator();
    long start=System.currentTimeMillis();
    while(it.hasNext()){
      System.out.print(it.next()+" ");
    }
    System.out.println();
    long end=System.currentTimeMillis();
    System.out.println("iterator for "+list.size()+":"+(end-start)+"ms");
  }


  private static void initList() {
    list1=new LinkedList<>();
    list2=new LinkedList<>();
    list3=new LinkedList<>();
    for(int i=0;i<10;i++){
      list1.add(random.nextInt());
    }
    for(int i=0;i<100;i++){
      list2.add(random.nextInt());
    }
    for(int i=0;i<1000;i++){
      list3.add(random.nextInt());
    }
  }
}

輸出(忽略對(duì)元素的輸出)

for for 10:0ms
foreach for 10:1ms
iterator for 10:0ms

for for 100:1ms
foreach for 100:0ms
iterator for 100:3ms

for for 1000:23ms
foreach for 1000:25ms
iterator for 1000:4ms

10 100 1000
for 0ms 1ms 23ms
forEach 1ms 0ms 25ms
Iterator 0ms 3ms 4ms

結(jié)論

foreach的性能最不穩(wěn)定,for次之,Iterator最好

使用建議

  • 盡量使用Iterator進(jìn)行遍歷
  • 需要使用索引時(shí),使用遞增變量的開銷比f(wàn)or的要小

HashSet的比較

注:因Hash遍歷算法與其他類型不一致,所以取消了for循環(huán)的比較

代碼

public class TextHash {

  private static Random random;

  private static Set<Integer> set1;

  private static Set<Integer> set2;

  private static Set<Integer> set3;

  public static void execute(){
    random=new Random();
    initHash();
    testIteratorWith10Object();
    testForEachWith10Object();
    testIteratorWith100Object();
    testForEachWith100Object();
    testIteratorWith1000Object();
    testForEachWith1000Object();
  }

  private static void testIteratorWith10Object() {
    printIterator(set1);
  }

  private static void testForEachWith10Object() {
    printForeach(set1);
  }

  private static void testIteratorWith100Object() {
    printIterator(set2);
  }

  private static void testForEachWith100Object() {
    printForeach(set2);
  }

  private static void testIteratorWith1000Object() {
    printIterator(set3);
  }

  private static void testForEachWith1000Object() {
    printForeach(set3);
  }

  private static void initHash() {
    set1=new HashSet<>();
    set2=new HashSet<>();
    set3=new HashSet<>();
    for(int i=0;i<10;i++){
      set1.add(random.nextInt());
    }
    for(int i=0;i<100;i++){
      set2.add(random.nextInt());
    }
    for(int i=0;i<1000;i++){
      set3.add(random.nextInt());
    }
  }

  private static void printIterator(Set<Integer> data){
    System.out.println();
    System.out.print("data:");
    long start=System.currentTimeMillis();
    Iterator<Integer> it=data.iterator();
    while (it.hasNext()){
      System.out.print(it.next()+" ");
    }
    System.out.println();
    long end=System.currentTimeMillis();
    System.out.println("iterator for "+data.size()+":"+(end-start)+"ms");
  }

  private static void printForeach(Set<Integer> data){
    System.out.println();
    System.out.print("data:");
    long start=System.currentTimeMillis();
    for(int temp:data){
      System.out.print(temp+" ");
    }
    System.out.println();
    long end=System.currentTimeMillis();
    System.out.println("foreach for "+data.size()+":"+(end-start)+"ms");
  }
}

輸出(忽略對(duì)元素的輸出)

iterator for 10:0ms
foreach for 10:0ms

iterator for 100:6ms
foreach for 100:0ms

iterator for 1000:30ms
foreach for 1000:9ms

10 100 1000
foreach 0ms 0ms 9ms
Iterator 0ms 6ms 30ms

結(jié)論

foreach性能遙遙領(lǐng)先于Iterator

使用建議

以后就選foreach了,性能好,寫起來也方便。

總結(jié)

  • for循環(huán)性能在三者的對(duì)比中總體落于下風(fēng),而且開銷遞增幅度較大。以后即使在需要使用索引時(shí)我寧愿使用遞增變量也不會(huì)使用for了。
  • Iterator的性能在數(shù)組以及鏈表的表現(xiàn)都是最好的,應(yīng)該是JAVA的設(shè)計(jì)者優(yōu)化過了。在響應(yīng)時(shí)間敏感的情況下(例如web響應(yīng)),優(yōu)先考慮。
  • foreach的性能屬于兩者之間,寫法簡(jiǎn)單,時(shí)間不敏感的情況下我會(huì)盡量選用。

以上就是我對(duì)常見數(shù)據(jù)結(jié)構(gòu)遍歷機(jī)制的一點(diǎn)比較,雖然只是很初步,但是從中我也學(xué)到了很多東西,希望你們也有所收獲。

好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • springboot返回前端中文亂碼的解決

    springboot返回前端中文亂碼的解決

    這篇文章主要介紹了springboot返回前端中文亂碼的解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • eclipse漢化及jdk安裝環(huán)境配置超詳細(xì)教程(Java安裝教程)

    eclipse漢化及jdk安裝環(huán)境配置超詳細(xì)教程(Java安裝教程)

    這篇文章主要介紹了eclipse漢化及jdk安裝環(huán)境配置超詳細(xì)教程(Java安裝教程),本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • Java容器源碼LinkedList原理解析

    Java容器源碼LinkedList原理解析

    這篇文章主要介紹了Java容器源碼LinkedList原理解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-11-11
  • Java中的ArrayList底層源碼分析

    Java中的ArrayList底層源碼分析

    這篇文章主要介紹了Java中的ArrayList底層源碼分析,通過下標(biāo)讀取元素的速度很快,這是因?yàn)锳rrayList底層基于數(shù)組實(shí)現(xiàn),可以根據(jù)下標(biāo)快速的找到內(nèi)存地址,接著讀取內(nèi)存地址中存放的數(shù)據(jù),需要的朋友可以參考下
    2023-12-12
  • 淺析打開eclipse出現(xiàn)Incompatible JVM的解決方法

    淺析打開eclipse出現(xiàn)Incompatible JVM的解決方法

    本篇文章是對(duì)打開eclipse出現(xiàn)Incompatible JVM的解決方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-07-07
  • scala 讀取txt文件的方法示例

    scala 讀取txt文件的方法示例

    這篇文章主要介紹了scala 讀取txt文件的方法示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • SpringBoot Controller返回圖片的三種方式

    SpringBoot Controller返回圖片的三種方式

    在互聯(lián)網(wǎng)的世界里,圖片無處不在,它們是信息傳遞的重要媒介,也是視覺盛宴的一部分,而在Spring Boot項(xiàng)目中,如何優(yōu)雅地處理和返回圖片數(shù)據(jù),則成為了開發(fā)者們不得不面對(duì)的問題,今天,就讓我們一起來探索Spring Boot Controller的神奇轉(zhuǎn)換,需要的朋友可以參考下
    2024-07-07
  • 解決rror updating database.Cause:java.sql.SQLSyntaxErrorException問題

    解決rror updating database.Cause:java.sql.SQLSyntaxE

    這篇文章主要介紹了解決rror updating database.Cause:java.sql.SQLSyntaxErrorException問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • 基于Jackson實(shí)現(xiàn)API接口數(shù)據(jù)脫敏的示例詳解

    基于Jackson實(shí)現(xiàn)API接口數(shù)據(jù)脫敏的示例詳解

    用戶的一些敏感數(shù)據(jù),例如手機(jī)號(hào)、郵箱、身份證等信息,在數(shù)據(jù)庫(kù)以明文存儲(chǔ),但在接口返回?cái)?shù)據(jù)給瀏覽器(或三方客戶端)時(shí),希望對(duì)這些敏感數(shù)據(jù)進(jìn)行脫敏,所以本文就給大家介紹以惡如何利用Jackson實(shí)現(xiàn)API接口數(shù)據(jù)脫敏,需要的朋友可以參考下
    2023-08-08
  • spring cloud 使用Zuul 實(shí)現(xiàn)API網(wǎng)關(guān)服務(wù)問題

    spring cloud 使用Zuul 實(shí)現(xiàn)API網(wǎng)關(guān)服務(wù)問題

    這篇文章主要介紹了spring cloud 使用Zuul 實(shí)現(xiàn)API網(wǎng)關(guān)服務(wù)問題,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-05-05

最新評(píng)論

平南县| 永泰县| 白水县| 鸡西市| 广东省| 平谷区| 长沙市| 基隆市| 永吉县| 鹤壁市| 福泉市| 巴里| 长丰县| 兰州市| 商都县| 平谷区| 读书| 夏邑县| 湘潭市| 霍林郭勒市| 商河县| 蓬莱市| 台湾省| 屯门区| 龙游县| 商都县| 博爱县| 辽中县| 特克斯县| 日喀则市| 崇左市| 长泰县| 安康市| 花垣县| 奉节县| 无锡市| 邹平县| 都安| 辽阳市| 松溪县| 德庆县|