zoukankan      html  css  js  c++  java
  • 标记接口: RandomAccess

     RandomAccess接口

    如果我们用Java做开发的话,最常用的容器之一就是List集合了,而List集合中用的较多的就是ArrayList 和 LinkedList 两个类,这两者也常被用来做比较。因为最近在学习Java的集合类源码,对于这两个类自然是不能放过,于是乎,翻看他们的源码,我发现,ArrayList实现了一个叫做 RandomAccess 的接口,而 LinkedList 是没有的,

    public class ArrayList<E> extends AbstractList<E>
            implements List<E>, RandomAccess, Cloneable, java.io.Serializable
    
    public class LinkedList<E>
        extends AbstractSequentialList<E>
        implements List<E>, Deque<E>, Cloneable, java.io.Serializable
    

    打开源码后,发现接口里面什么也没有,这是个空的接口,并且是1.4才引入的

     * @since 1.4
     */
    public interface RandomAccess {
    }
    

    那么这个接口是做什么的?

    标志接口

    通过官网的API,我才知道,原来这是一个标志接口,下面引入一段官网的原文:

    public interface RandomAccess

    Marker interface used by List implementations to indicate that they support fast (generally constant time) random access.

    这段话大概的意思就是说 RandomAccess 是一个标志接口,表明实现这个这个接口的 List 集合是支持快速随机访问的。也就是说,实现了这个接口的集合是支持 快速随机访问 策略的。

    同时,官网还特意说明了,如果是实现了这个接口的 List,那么使用for循环的方式获取数据会优于用迭代器获取数据。

    As a rule of thumb, aList 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);

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

    下面做个测试吧,以ArrayList 为例。

    Demo测试

    分别创建两个方法,一个用for循环 get() 数据的方式遍历集合,另一个是用迭代器,分别返回所用的时间:

    public static long arrayFor() {
        List<Integer> list = new ArrayList<Integer>();
        for (int i = 1; i <= 100000; i++) {
            list.add(i);
        }
        //开始时间
        long startTime = System.currentTimeMillis();
    
        for (int j = 0; j < list.size(); j++) {
            Object num = list.get(j);
        }
    
        //结束时间
        long endTime = System.currentTimeMillis();
    
        //返回所用时间
        return endTime-startTime;
    }
    
    public static long arrayIterator() {
        List<Integer> list = new ArrayList<Integer>();
        for (int i = 1; i <= 100000; i++) {
            list.add(i);
        }
        long startTime = System.currentTimeMillis();
    
        Iterator iterator = list.iterator();
        while (iterator.hasNext()){
            Object next = iterator.next();
        }
    
        long endTime = System.currentTimeMillis();
    
        return endTime-startTime;
    }
    

    接着,在mian方法中测试:

    public static void main(String[] args) {
        long time1 = arrayFor();
        long time2 = arrayIterator();
    
        System.out.println("ArrayList for循环所用时间=="+time1);
        System.out.println("ArrayList 迭代器所用时间=="+time2);
    }
    

    运行程序,输出结果

    ArrayList for循环所用时间==2
    ArrayList 迭代器所用时间==3
    

    可以看出,for循环遍历元素时间上是少于迭代器的,证明RandomAccess 接口确实是有这个效果。

    当然,现在的语言和机器性能这么高,两种方式遍历数据的性能差距几乎可以忽略不计,尤其是数据量不大的情况下。所以,我觉得,日常使用中没必要过分追求哪种方式好,按照自己的习惯来就行。

  • 相关阅读:
    LeetCode 1110. Delete Nodes And Return Forest
    LeetCode 473. Matchsticks to Square
    LeetCode 886. Possible Bipartition
    LeetCode 737. Sentence Similarity II
    LeetCode 734. Sentence Similarity
    LeetCode 491. Increasing Subsequences
    LeetCode 1020. Number of Enclaves
    LeetCode 531. Lonely Pixel I
    LeetCode 1091. Shortest Path in Binary Matrix
    LeetCode 590. N-ary Tree Postorder Traversal
  • 原文地址:https://www.cnblogs.com/muzhongjiang/p/12823334.html
Copyright © 2011-2022 走看看