成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

JAVA遍歷機(jī)制的性能的比較

mudiyouyou / 3347人閱讀

摘要:總結(jié)循環(huán)性能在三者的對(duì)比中總體落于下風(fēng),而且開(kāi)銷(xiāo)遞增幅度較大。的性能在數(shù)組以及鏈表的表現(xiàn)都是最好的,應(yīng)該是的設(shè)計(jì)者優(yōu)化過(guò)了。

????本文首發(fā)于cartoon的博客
????轉(zhuǎn)載請(qǐng)注明出處:https://cartoonyu.github.io/cartoon-blog/post/java/java%E9%81%8D%E5%8E%86%E6%9C%BA%E5%88%B6%E7%9A%84%E6%80%A7%E8%83%BD%E6%AF%94%E8%BE%83/

緣由

????近段時(shí)間在寫(xiě)leetcode的Lemonade Change時(shí)候,發(fā)現(xiàn)了for循環(huán)與forEach循環(huán)的耗時(shí)是不一致的,在提交記錄上面差了一倍......
????平常開(kāi)發(fā)絕大部分業(yè)務(wù)邏輯的實(shí)現(xiàn)都需要遍歷機(jī)制的幫忙,雖說(shuō)也有注意到各數(shù)據(jù)結(jié)構(gòu)操作的性能比較,但是忽視了遍歷機(jī)制性能的差異。原本前兩天就開(kāi)始動(dòng)手寫(xiě),拖延癥......

正文

????現(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é)來(lái)說(shuō),JAVA的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu),我覺(jué)得有兩種

數(shù)組

鏈表

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

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

ArrayList(包裝后的數(shù)組)

LinkedList(包裝后的鏈表)

HashSet(包裝后的Hash類(lèi)型數(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。如果你有閱讀過(guò)源碼就會(huì)發(fā)現(xiàn):每個(gè)Set子類(lèi)的實(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í)間開(kāi)銷(xiāo)受本地環(huán)境的影響,可能測(cè)量值會(huì)出現(xiàn)變化,但是總體上比例是正確的

ArrayList的比較

代碼

public class TextArray {

    private static Random random;

    private static List list1;

    private static List list2;

    private static List 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 list){
        System.out.println();
        System.out.print("data:");
        long start=System.currentTimeMillis();
        for(int i=0,length=list.size();i 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 list){
        System.out.println();
        System.out.print("data:");
        Iterator 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í),使用遞增變量的開(kāi)銷(xiāo)比f(wàn)or的要小

LinkedList的比較

代碼

public class TextLinkedList {

    private static Random random;

    private static List list1;

    private static List list2;

    private static List 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 list){
        System.out.println();
        System.out.print("data:");
        long start=System.currentTimeMillis();
        for(int i=0,size=list.size();i 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 list){
        System.out.println();
        System.out.print("data:");
        Iterator 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í),使用遞增變量的開(kāi)銷(xiāo)比f(wàn)or的要小

HashSet的比較

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

代碼

public class TextHash {

    private static Random random;

    private static Set set1;

    private static Set set2;

    private static Set 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 data){
        System.out.println();
        System.out.print("data:");
        long start=System.currentTimeMillis();
        Iterator 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 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了,性能好,寫(xiě)起來(lái)也方便。

總結(jié)

for循環(huán)性能在三者的對(duì)比中總體落于下風(fēng),而且開(kāi)銷(xiāo)遞增幅度較大。以后即使在需要使用索引時(shí)我寧愿使用遞增變量也不會(huì)使用for了。

Iterator的性能在數(shù)組以及鏈表的表現(xiàn)都是最好的,應(yīng)該是JAVA的設(shè)計(jì)者優(yōu)化過(guò)了。在響應(yīng)時(shí)間敏感的情況下(例如web響應(yīng)),優(yōu)先考慮。

foreach的性能屬于兩者之間,寫(xiě)法簡(jiǎn)單,時(shí)間不敏感的情況下我會(huì)盡量選用。

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

????如果你喜歡本文章,可以收藏閱讀,如果你對(duì)我的其他文章感興趣,歡迎到我的博客查看。

列表項(xiàng)目

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/74894.html

相關(guān)文章

  • 帶你了解集合世界fail-fast機(jī)制 和 CopyOnWriteArrayList 源碼詳解

    摘要:體現(xiàn)的就是適配器模式。數(shù)組對(duì)象集合世界中的機(jī)制機(jī)制集合世界中比較常見(jiàn)的錯(cuò)誤檢測(cè)機(jī)制,防止在對(duì)集合進(jìn)行遍歷過(guò)程當(dāng)中,出現(xiàn)意料之外的修改,會(huì)通過(guò)異常暴力的反應(yīng)出來(lái)。而在增強(qiáng)循環(huán)中,集合遍歷是通過(guò)進(jìn)行的。 前言 學(xué)習(xí)情況記錄 時(shí)間:week 2 SMART子目標(biāo) :Java 容器 記錄在學(xué)習(xí)Java容器 知識(shí)點(diǎn)中,關(guān)于List的重點(diǎn)知識(shí)點(diǎn)。 知識(shí)點(diǎn)概覽: 容器中的設(shè)計(jì)模式 從Array...

    young.li 評(píng)論0 收藏0
  • NIO網(wǎng)絡(luò)相關(guān)基礎(chǔ)知識(shí)

    摘要:操作系統(tǒng)是能夠獲取到事件操作完成的事件,基于回調(diào)函數(shù)機(jī)制和操作系統(tǒng)的操作控制實(shí)現(xiàn)事件檢測(cè)機(jī)制。 前面的文章NIO基礎(chǔ)知識(shí)介紹了Java NIO的一些基本的類(lèi)及功能說(shuō)明,Java NIO是用來(lái)替換java 傳統(tǒng)IO的,NIO的一些新的特性在網(wǎng)絡(luò)交互方面會(huì)更加的明顯。 Java 傳統(tǒng)IO的弊端 ????基于JVM來(lái)實(shí)現(xiàn)每個(gè)通道的輪詢檢查通道狀態(tài)的方法是可行的,但仍然是有問(wèn)題的,檢查每個(gè)通道...

    1fe1se 評(píng)論0 收藏0
  • 類(lèi)加載機(jī)制 - 收藏集 - 掘金

    摘要:是現(xiàn)在廣泛流行的代從開(kāi)始學(xué)習(xí)系列之向提交代碼掘金讀完本文大概需要分鐘。為了進(jìn)行高效的垃圾回收,虛擬機(jī)把堆內(nèi)存劃分成新生代老年代和永久代中無(wú)永久代,使用實(shí)現(xiàn)三塊區(qū)域。 React Native 開(kāi)源項(xiàng)目 - 仿美團(tuán)客戶端 (Android、iOS 雙適配) - Android - 掘金推薦 React Native 學(xué)習(xí)好項(xiàng)目,仿照美團(tuán)客戶端... 極簡(jiǎn) GitHub 上手教程 - 工具...

    Gilbertat 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<