一、背景
在学习 Java
集合时, 最先学习的便是 List
中的 ArrayList
和 LinkedList
, 学习集合很关键的是学习其源码, 了解底层实现方式, 在学习的过程中,发现了一个有趣的类,就是RandomAccess
,奔着好奇,加技术探索的心情,那么今天就讲讲 ArrayList
实现的一个接口 RandomAccess
到底有什么作用呢。
二、标记接口
通过查阅相关资料,了解到这种类型的接口可以称之为标记接口,用于标记这个类拥有某种特定的功能,就好比当前的RandomAccess
这个接口就标记这ArrayList
拥有被快速访问的功能。我们通过一段代码来更深入的了解一下这个接口:
public class Test1 {
public static void main(String[] args) {
List<Integer> list1 = new ArrayList<>();
for (int i = 0; i < 1000000; i++) {
list1.add(i);
}
//可以快速访问 直接是有get
if (list1 instanceof RandomAccess) {
for (int i = 0; i < list1.size(); i++) {
System.out.println(list1.get(i));
}
} else {
//使用迭代器方式
Iterator<Integer> iterator = list1.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
}
通过instanceof
关键字快速判断对象集体使用那种方式进行循环,到这是不是看不出他到底有什么作用,在看下面这个不同类型的集合使用不同方式循环所用的时间:
class TimeTest {
//使用for循环遍历
public static long useByLoop(List list) {
long startTime = System.currentTimeMillis();
for (int i = 0; i < list.size(); i++) {
list.get(i);
}
long endTime = System.currentTimeMillis();
return endTime - startTime;
}
//使用迭代器遍历
public static long useByIterator(List list) {
Iterator iterator = list.iterator();
long startTime = System.currentTimeMillis();
while (iterator.hasNext()) {
iterator.next();
}
long endTime = System.currentTimeMillis();
return endTime - startTime;
}
public static void main(String[] args) {
//加入数据
List<String> arrayList = new ArrayList<>();
for (int i = 0; i < 300000; i++) {
arrayList.add("" + i);
}
long loopTime = TimeTest.useByLoop(arrayList);
long iteratorTime = TimeTest.useByLoop(arrayList);
System.out.println("ArrayList:");
System.out.println("for循环遍历时间:" + loopTime);
System.out.println("迭代器遍历时间:" + iteratorTime);
List<String> linkedList = new LinkedList<>();
//加入数据
for (int i = 0; i < 30000; i++) {
linkedList.add("" + i);
}
loopTime = TimeTest.useByLoop(linkedList);
iteratorTime = TimeTest.useByLoop(linkedList);
System.out.println("LinkedList:");
System.out.println("for循环遍历时间:" + loopTime);
System.out.println("迭代器遍历时间:" + iteratorTime);
}
}
很明显ArrayList
使用for
循环的方式比迭代的方式要快一些,而从LinkedList
使用迭代的方式要快一些,对于ArrayList
和LinkedList
来说前者底层原理是数组,可以直接通过下标直接访问,而对于后者来说他的底层实现方式为链表,组支持随机访问, 查询速度快, 增删元素慢; 链表支持顺序访问, 查询速度慢, 增删元素快。这也是为什么ArrayList
实现了RandomAccess
而LinkedList
没有实现的原因,因为他可以通过instanceof
关键字快速判断对象集体使用那种方式效率最高,这里仅仅是已这个为例子,当然标记接口的功能实现就是这种方式,具体实现的功能肯定都是不一样的。但是实现方式都是大同小异。
三、总结
标记接口就是标记该类是否拥有某种功能,或者是否可以进行某种操作等等的一种实现方式,在开发中我们也可以使用这种方式来限定特定的需求。