RandomAccess介面理解

-Billy發表於2018-08-10

根據javadoc上面的的解釋是:

RandomAccess 是一個標記介面,用於標明實現該介面的List支援快速隨機訪問,主要目的是使演算法能夠在隨機和順序訪問的list中表現的更加高效。

我們可以簡單的看下Collections下的binarySearch方法的原始碼:

  1. public static <T>
  2. int binarySearch(List<? extends Comparable<? super T>> list, T key) {
  3. if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
  4. return Collections.indexedBinarySearch(list, key);
  5. else
  6. return Collections.iteratorBinarySearch(list, key);
  7. }


從原始碼中我們可以看到,在進行二分查詢的時候,list會先判斷是否是RandomAccess也即是否實現了RandomAccess介面,接著在呼叫想用的二分查詢演算法來進行,(其中: BINARYSEARCH_THRESHOLD Collections的一個常量(5000),它是二分查詢的閥值。)如果實現了RandomAccess介面的List,執行indexedBinarySearch方法,否則執行 iteratorBinarySearch方法。

分別看下這兩個方法的實現:


indexedBinarySearch 方法:

  1. private static <T>
  2. int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key) {
  3. int low = 0;
  4. int high = list.size()-1;
  5. while (low <= high) {
  6. int mid = (low + high) >>> 1;
  7. Comparable<? super T> midVal = list.get(mid);
  8. int cmp = midVal.compareTo(key);
  9. if (cmp < 0)
  10. low = mid + 1;
  11. else if (cmp > 0)
  12. high = mid - 1;
  13. else
  14. return mid; // key found
  15. }
  16. return -(low + 1); // key not found
  17. }

indexedBinarySearch 方法是直接通過get來訪問元素


iteratorBinarySearch方法:

  1. private static <T>
  2. int iteratorBinarySearch(List<? extends Comparable<? super T>> list, T key)
  3. {
  4. int low = 0;
  5. int high = list.size()-1;
  6. ListIterator<? extends Comparable<? super T>> i = list.listIterator();
  7. while (low <= high) {
  8. int mid = (low + high) >>> 1;
  9. Comparable<? super T> midVal = get(i, mid);
  10. int cmp = midVal.compareTo(key);
  11. if (cmp < 0)
  12. low = mid + 1;
  13. else if (cmp > 0)
  14. high = mid - 1;
  15. else
  16. return mid; // key found
  17. }
  18. return -(low + 1); // key not found
  19. }
iteratorBinarySearch中ListIterator來查詢相應的元素


javadoc中特別指出:

It is recognized that the distinction between random and sequential access is often fuzzy. For example, some List implementations provide asymptotically linear access times if they get huge, but constant access times in practice. Such a Listimplementation should generally implement this interface. As a rule of thumb, a List implementation should implement this interface if, for typical instances of the class, this loop:

     for (int i=0, n=list.size(); i < n; i++)
         list.get(i);
 

runs faster than this loop:

     for (Iterator i=list.iterator(); i.hasNext(); )
         i.next();


總結:實現RandomAccess介面的的List可以通過簡單的for迴圈來訪問資料比使用iterator訪問來的高效快速。

參考文件:https://docs.oracle.com/javase/7/docs/api/java/util/RandomAccess.html





        </div>
            </div>
        </article>

相關文章