一、背景

在学习 Java 集合时, 最先学习的便是 List中的 ArrayListLinkedList, 学习集合很关键的是学习其源码, 了解底层实现方式, 在学习的过程中,发现了一个有趣的类,就是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);
    }
}

java 标记废弃字段 java 标记接口_System


很明显ArrayList使用for循环的方式比迭代的方式要快一些,而从LinkedList使用迭代的方式要快一些,对于ArrayListLinkedList来说前者底层原理是数组,可以直接通过下标直接访问,而对于后者来说他的底层实现方式为链表,组支持随机访问, 查询速度快, 增删元素慢; 链表支持顺序访问, 查询速度慢, 增删元素快。这也是为什么ArrayList实现了RandomAccessLinkedList没有实现的原因,因为他可以通过instanceof关键字快速判断对象集体使用那种方式效率最高,这里仅仅是已这个为例子,当然标记接口的功能实现就是这种方式,具体实现的功能肯定都是不一样的。但是实现方式都是大同小异。

三、总结

标记接口就是标记该类是否拥有某种功能,或者是否可以进行某种操作等等的一种实现方式,在开发中我们也可以使用这种方式来限定特定的需求。