zoukankan      html  css  js  c++  java
  • 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 接口确实是有这个效果。

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

  • 相关阅读:
    Redis21:客户端与服务器端的通信与redis管道
    Redis20:keys、scan、bigkeys、查看key的存储方式
    Redis19:限流
    Redis18:分布式锁
    Redis17:cluster集群
    Redis16:两种redis集群解决方案:codis和cluster
    Android : 获取声卡信息的测试代码
    Android : 基于alsa库的音乐播放
    Android system :灯光系统_HAL_lights
    Android system :led_class驱动
  • 原文地址:https://www.cnblogs.com/yeya/p/9950723.html
Copyright © 2011-2022 走看看