标记接口,Marker interface,它们是一类没有定义任何接口方法的接口,表现为一个空接口
没有接口方法意味着实现该接口的类无需实现任何接口方法,仅仅作为一种标记,以供其他方法判断
作用就是当某个类实现这个接口后即拥有了这个接口的功能,Java 虚拟机在运行时会识别到它
标记接口是Java的语言特性
RandomAccess
在计算机科学中,随机访问(RandomAccess)是从大量的可寻址元素的数据中访问任何元素大致和访问其他元素一样简洁有效,不管多少元素在这个集合中。与随机访问相反的是顺序访问(SequenceAccess)
RandomAccess 就是一个标记接口,用于标明实现该接口的List支持快速随机访问,主要目的是使算法能够在随机和顺序访问的List中性能更加高效(在Collections二分查找时)。
Collections的binarySearch方法:
public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key) {
if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
return Collections.indexedBinarySearch(list, key);
else
return Collections.iteratorBinarySearch(list, key);
}
在进行二分查找时,首先判断list是否实现了RandomAccess,然后选择执行最优算法。
如果集合类是RandomAccess的实现,则尽量用for(int i = 0; i < size; i++) 即for循环来遍历,而不是用Iterator
迭代器来进行迭代。
JDK中说的很清楚,在对List特别是Huge size的List的遍历算法中,要尽量来判断是属于RandomAccess(如:ArrayList)还是SequenceAccess(如:LinkedList)
源码翻译
/*
* Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package java.util;
/**
* Marker interface used by <tt>List</tt> implementations to indicate that
* they support fast (generally constant time) random access. The primary
* purpose of this interface is to allow generic algorithms to alter their
* behavior to provide good performance when applied to either random or
* sequential access lists.
* List实现所使用的标记接口,用来表明实现了这些接口的list支持快速(通常是常数时间)随机访问。
* 这个接口的主要目的是允许一般的算法更改它们的行为,以便在随机或者顺序存取列表时能提供更好的性能
* <p>The best algorithms for manipulating random access lists (such as
* <tt>ArrayList</tt>) can produce quadratic behavior when applied to
* sequential access lists (such as <tt>LinkedList</tt>). Generic list
* algorithms are encouraged to check whether the given list is an
* <tt>instanceof</tt> this interface before applying an algorithm that would
* provide poor performance if it were applied to a sequential access list,
* and to alter their behavior if necessary to guarantee acceptable
* performance.
* 操作随机访问列表(如ArrayList)的最佳算法在应用于顺序存取列表时,有可能产生二次项行为。
* 泛型算法列表鼓励在将某个算法应用于顺序存取列表可能导致差的性能之前,先检查给定的列表是
* 否是这个接口的一个实例,并在需要时去改变这些算法的行为以保证性能。
* <p>It is recognized that the distinction between random and sequential
* access is often fuzzy. For example, some <tt>List</tt> implementations
* provide asymptotically linear access times if they get huge, but constant
* access times in practice. Such a <tt>List</tt> implementation
* should generally implement this interface. As a rule of thumb, a
* <tt>List</tt> implementation should implement this interface if,
* for typical instances of the class, this loop:
* 随机访问和顺序存取之间的界限通常是模糊的。例如,一些List实现在变得很大时会导致渐进的非
* 线性访问时间,但实际上是常量访问时间。这样的List实现通常都应该实现该接口。一般来说,某
* 个List实现如果(对某些典型的类的实例来说)满足下面的条件,就应该实现这个接口:循环
* <pre>
* for (int i=0, n=list.size(); i < n; i++)
* list.get(i);
* </pre>
* runs faster than this loop:
* 比下面的循环运行速度快。
* <pre>
* for (Iterator i=list.iterator(); i.hasNext(); )
* i.next();
* </pre>
*
* @since 1.4
*/
public interface RandomAccess {
}
总结
RandomAccess是一个空接口,而空接口的作用一般是起到一个标识的作用。
通俗点讲,就是判断一个list是否实现了RandomAcess接口,如果实现了,采用简单的for循环进行访问速度比较快。
如果未实现RandomAcess接口,则采用iterator循环访问速度比较快。
判断使用instanceof,即
if (list instanceof RandomAccess)