ArrayList、LinkedList都是Java中常用的两种List类型。其中大家有没有发现ArrayList实现了RandomAccess的标记接口(空接口),那么为什么要实现一个方法都没有的空接口呢?
RandomAccess源码注释这样说的:
Marker interface used by List 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.
// 在数据量较大的情况下(自己可以写个简单的例子实验一下)
// 实现RandomAccess的接口用索引遍历更快,本质就是数组支持常量时间的随机访问
for (int i=0, n=list.size(); i < n; i++)
list.get(i);
// 没有实现RandomAccess接口,使用迭代器遍历更快些
for (Iterator i=list.iterator(); i.hasNext(); )
i.next();
我们可以看看Collections中的例子就明白了,其实很简单,就是用来判断是否支持随机访问,然后对应选择索引遍历还是迭代器遍历。
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);
}
再来一个netty的例子
io.netty.handler.codec.smtp.SmtpRequestEncoder#writeParameters
private static void writeParameters(List<CharSequence> parameters, ByteBuf out, boolean commandNotEmpty) {
if (parameters.isEmpty()) {
return;
}
if (commandNotEmpty) {
out.writeByte(SP);
}
if (parameters instanceof RandomAccess) {
final int sizeMinusOne = parameters.size() - 1;
for (int i = 0; i < sizeMinusOne; i++) {
ByteBufUtil.writeAscii(out, parameters.get(i));
out.writeByte(SP);
}
ByteBufUtil.writeAscii(out, parameters.get(sizeMinusOne));
} else {
final Iterator<CharSequence> params = parameters.iterator();
for (;;) {
ByteBufUtil.writeAscii(out, params.next());
if (params.hasNext()) {
out.writeByte(SP);
} else {
break;
}
}
}
}
所以在数据量较大或者性能要求高的地方,RandomAccess就很有用了。通常可以用在框架代码里面。