<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          ArrayList 為什么要實(shí)現(xiàn) RandomAccess 接口?

          共 776字,需瀏覽 2分鐘

           ·

          2020-08-09 02:20

          點(diǎn)擊上方藍(lán)色“程序猿DD”,選擇“設(shè)為星標(biāo)”

          回復(fù)“資源”獲取獨(dú)家整理的學(xué)習(xí)資料!

          來(lái)源 |?http://t.cn/AilfR3YW

          在我們的開(kāi)發(fā)中,List接口是最常見(jiàn)不過(guò),而且我們幾乎每天都在用ArrayList或者LinkedList,但是細(xì)心的同學(xué)有沒(méi)有發(fā)現(xiàn),ArrayList中實(shí)現(xiàn)了RandomAccess接口,而LinkedList卻沒(méi)有實(shí)現(xiàn)RandomAccess接口,這是為什么呢?

          public?class?ArrayList<E>?extends?AbstractList<E>
          ????????implements?List<E>,?RandomAccess,?Cloneable,?java.io.Serializable
          public?class?LinkedList<E>
          ????extends?AbstractSequentialList<E>
          ????implements?List<E>,?Deque<E>,?Cloneable,?java.io.Serializable

          RandomAccess接口中是空的,RandomAccess接口又是什么呢?

          public?interface?RandomAccess?{
          }

          RandomAccess接口

          RandomAccess是一個(gè)標(biāo)記接口,官方解釋是只要List實(shí)現(xiàn)這個(gè)接口,就能支持快速隨機(jī)訪問(wèn)。而什么是隨機(jī)訪問(wèn)呢?接下來(lái)我們來(lái)舉例說(shuō)明。

          Collections是集合的一個(gè)工具類,我們看一下Collections源碼中的二分搜索方法。

          public?static?
          ????int?binarySearch(Listsuper?T>>?list,?T?key)?{
          ????????if?(list?instanceof?RandomAccess?||?list.size()????????????return?Collections.indexedBinarySearch(list,?key);
          ????????else
          ????????????return?Collections.iteratorBinarySearch(list,?key);
          ????}

          在源碼中可以看出,判斷l(xiāng)ist是否是RandomAccess的實(shí)例,如果是,則執(zhí)行indexedBinarySearch方法,如果不是,則執(zhí)行iteratorBinarySearch方法。接下來(lái)看一下這兩個(gè)方法。

          private?static?
          int?indexedBinarySearch(Listsuper?T>>?list,?T?key)?{
          ????int?low?=?0;
          ????int?high?=?list.size()-1;

          ????while?(low?<=?high)?{
          ????????int?mid?=?(low?+?high)?>>>?1;
          ????????Comparablesuper?T>?midVal?=?list.get(mid);
          ????????int?cmp?=?midVal.compareTo(key);

          ????????if?(cmp?0)
          ????????????low?=?mid?+?1;
          ????????else?if?(cmp?>?0)
          ????????????high?=?mid?-?1;
          ????????else
          ????????????return?mid;?//?key?found
          ????}
          ????return?-(low?+?1);??//?key?not?found
          }
          private?static?
          int?iteratorBinarySearch(Listsuper?T>>?list,?T?key)
          {
          ????int?low?=?0;
          ????int?high?=?list.size()-1;
          ????ListIteratorsuper?T>>?i?=?list.listIterator();

          ????while?(low?<=?high)?{
          ????????int?mid?=?(low?+?high)?>>>?1;
          ????????Comparablesuper?T>?midVal?=?get(i,?mid);
          ????????int?cmp?=?midVal.compareTo(key);

          ????????if?(cmp?0)
          ????????????low?=?mid?+?1;
          ????????else?if?(cmp?>?0)
          ????????????high?=?mid?-?1;
          ????????else
          ????????????return?mid;?//?key?found
          ????}
          ????return?-(low?+?1);??//?key?not?found
          }

          上述兩個(gè)方法的源碼表示,實(shí)現(xiàn)了RandomAccess接口的List使用索引遍歷,而未實(shí)現(xiàn)RandomAccess接口的List使用迭代器遍歷。那么為什么要這么設(shè)計(jì)呢?
          既然涉及到二分搜索的遍歷操作,那么現(xiàn)在我們來(lái)分析一下ArrayList和LinkedList遍歷元素的性能如何?

          public?class?CollectionTest?{
          ????public?static?void?main(String[]?args){
          ????????long?arrayListIndexedTime?=?arrayListIndexed();
          ????????long?arrayListIteratorTime?=?arrayListIterator();
          ????????long?linkedListIndexedTime?=?linkedListIndexed();
          ????????long?linkedListIteratorTime?=?linkedListIterator();
          ????????System.out.println("測(cè)試ArrayList通過(guò)for遍歷所消耗時(shí)間:"?+?arrayListIndexedTime);
          ????????System.out.println("測(cè)試ArrayList通過(guò)iterator遍歷所消耗時(shí)間:"?+?arrayListIteratorTime);
          ????????System.out.println("測(cè)試LinkedList通過(guò)for遍歷所消耗時(shí)間:"?+?linkedListIndexedTime);
          ????????System.out.println("測(cè)試LinkedList通過(guò)iterator遍歷所消耗時(shí)間:"?+?linkedListIteratorTime);
          ????}

          ????//測(cè)試ArrayList通過(guò)for遍歷所消耗時(shí)間
          ????public?static?long?arrayListIndexed()?{
          ????????List?arrayList?=?new?ArrayList<>();
          ????????for?(int?i?=?0;?i?10000;?i++)?{
          ????????????arrayList.add(i);
          ????????}
          ????????//記錄開(kāi)始時(shí)間
          ????????long?startTime?=?System.currentTimeMillis();
          ????????for?(int?i?=?0;?i?????????????arrayList.get(i);
          ????????}
          ????????//記錄結(jié)束時(shí)間
          ????????long?endTime?=?System.currentTimeMillis();
          ????????//遍歷消耗時(shí)間
          ????????long?resultTime?=?endTime?-?startTime;
          ????????return?resultTime;
          ????}

          ????//測(cè)試ArrayList通過(guò)iterator遍歷所消耗時(shí)間
          ????public?static?long?arrayListIterator()?{
          ????????List?arrayList?=?new?ArrayList<>();
          ????????for?(int?i?=?0;?i?10000;?i++)?{
          ????????????arrayList.add(i);
          ????????}
          ????????//記錄開(kāi)始時(shí)間
          ????????long?startTime?=?System.currentTimeMillis();
          ????????Iterator?iterator?=?arrayList.iterator();
          ????????while?(iterator.hasNext())?{
          ????????????iterator.next();
          ????????}
          ????????//記錄結(jié)束時(shí)間
          ????????long?endTime?=?System.currentTimeMillis();
          ????????//遍歷消耗時(shí)間
          ????????long?resultTime?=?endTime?-?startTime;
          ????????return?resultTime;
          ????}

          ????//測(cè)試LinkedList通過(guò)for遍歷所消耗時(shí)間
          ????public?static?long?linkedListIndexed()?{
          ????????List?linkedList?=?new?LinkedList<>();
          ????????for?(int?i?=?0;?i?10000;?i++)?{
          ????????????linkedList.add(i);
          ????????}
          ????????//記錄開(kāi)始時(shí)間
          ????????long?startTime?=?System.currentTimeMillis();
          ????????for?(int?i?=?0;?i?????????????linkedList.get(i);
          ????????}
          ????????//記錄結(jié)束時(shí)間
          ????????long?endTime?=?System.currentTimeMillis();
          ????????//遍歷消耗時(shí)間
          ????????long?resultTime?=?endTime?-?startTime;
          ????????return?resultTime;
          ????}

          ????//測(cè)試LinkedList通過(guò)iterator遍歷所消耗時(shí)間
          ????public?static?long?linkedListIterator()?{
          ????????List?linkedList?=?new?LinkedList<>();
          ????????for?(int?i?=?0;?i?10000;?i++)?{
          ????????????linkedList.add(i);
          ????????}
          ????????//記錄開(kāi)始時(shí)間
          ????????long?startTime?=?System.currentTimeMillis();
          ????????Iterator?iterator?=?linkedList.iterator();
          ????????while?(iterator.hasNext())?{
          ????????????iterator.next();
          ????????}
          ????????//記錄結(jié)束時(shí)間
          ????????long?endTime?=?System.currentTimeMillis();
          ????????//遍歷消耗時(shí)間
          ????????long?resultTime?=?endTime?-?startTime;
          ????????return?resultTime;
          ????}
          }

          測(cè)試結(jié)果如下

          測(cè)試ArrayList通過(guò)for遍歷所消耗時(shí)間:1
          測(cè)試ArrayList通過(guò)iterator遍歷所消耗時(shí)間:2
          測(cè)試LinkedList通過(guò)for遍歷所消耗時(shí)間:47
          測(cè)試LinkedList通過(guò)iterator遍歷所消耗時(shí)間:1

          我們來(lái)分析一下測(cè)試結(jié)果:ArrayList通過(guò)for遍歷比通過(guò)iterator遍歷要稍快,LinkedList通過(guò)iterator遍歷比通過(guò)for遍歷要快。

          所以說(shuō)在我們的應(yīng)用中,要考慮使用List接口的哪種實(shí)現(xiàn)類,可以更好更高效的滿足實(shí)際場(chǎng)景需求。所以在這里通過(guò)實(shí)現(xiàn)RandomAccess接口來(lái)區(qū)分List的哪種實(shí)現(xiàn)類。

          總結(jié)

          最后總結(jié)一句話:實(shí)現(xiàn)RandomAccess接口的List可以通過(guò)for循環(huán)來(lái)遍歷數(shù)據(jù)比使用iterator遍歷數(shù)據(jù)更高效,未實(shí)現(xiàn)RandomAccess接口的List可以通過(guò)iterator遍歷數(shù)據(jù)比使用for循環(huán)來(lái)遍歷數(shù)據(jù)更高效。


          往期推薦

          為什么阿里規(guī)定事務(wù)注解@Transactional中指定rollbackFor?

          面試:說(shuō)說(shuō)參數(shù)驗(yàn)證 @Validated 和 @Valid 的區(qū)別?

          SQL查找是否"存在",別再count了!

          IntelliJ IDEA 2020.2 發(fā)布:支持Java 15、GitHub審查...

          Mybatis 框架下 SQL 注入攻擊的 3 種方式,真是防不勝防!


          歡迎加入我的知識(shí)星球,聊技術(shù)、說(shuō)職場(chǎng)、侃社會(huì)。



          星球兩大分享內(nèi)容

          瀏覽 53
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  麻豆传媒一区二区在线观看 | 色蜜桃av | 99这里只有精品视频 | 青青草视频黄色在线观看 | 色老板最新凹凸视频 |