RandomAccess接口的主要作用

在List集合这个大家族中,有许多类型的List实现了RandomAccess接口,那么这个接口有什么作用呢。

通过查看RandomAccess的源码我们可以知道,这个接口用来表明支持快速随机访问。快速随机访问的速度能做到比线性访问的速度还要快。源码中也举了个例子做对比。

for (int i = 0, n = list.size(); i < n; i++)
     list.get(i);
     
// runs faster than this loop:

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

通过get()方法(随机访问)要比迭代器中的next()方法(线性访问)速度要快。

再来看下List集合中两个常用的类 ArrayListLinkedList
其中ArrayList实现了RandomAccess接口,而LinkedList没有实现。我们测试一下二者通过随机访问和迭代器的线性访问的速度。

ArrayList

public class Test {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 10000; i++) {
            list.add(i);
        }

        long start = System.nanoTime();
        for (int i = 0, n = list.size(); i < n; i++) {
            list.get(i);
        }
        long end = System.nanoTime();
        System.out.println("实现了RandomAccess接口的随机访问时间:  " + (end - start));

        start = System.nanoTime();
        for (Iterator<Integer> it = list.iterator(); it.hasNext(); ) {
            it.next();
        }
        end = System.nanoTime();
        System.out.println("实现了RandomAccess接口的线性访问时间:  " + (end - start));
    }
}

// 结果
实现了RandomAccess接口的随机访问时间:  341300
实现了RandomAccess接口的线性访问时间:  723400

LinkedList

public class Test {
    public static void main(String[] args) {
        List<Integer> list = new LinkedList<>();
        for (int i = 0; i < 10000; i++) {
            list.add(i);
        }

        long start = System.nanoTime();
        for (int i = 0, n = list.size(); i < n; i++) {
            list.get(i);
        }
        long end = System.nanoTime();
        System.out.println("没有实现RandomAccess接口的随机访问时间:  " + (end - start));

        start = System.nanoTime();
        for (Iterator<Integer> it = list.iterator(); it.hasNext(); ) {
            it.next();
        }
        end = System.nanoTime();
        System.out.println("没有实现RandomAccess接口的线性访问时间:  " + (end - start));
    }
}

// 结果
没有实现RandomAccess接口的随机访问时间:  33793400
没有实现RandomAccess接口的线性访问时间:  867900

可以看出,实现了RandomAccess接口的情况下,随机访问的速度更快;没有实现RandomAccess接口的情况下,线性访问更快。所以遍历集合时,不同的遍历方式的效率也是不同的,我们要根据情况选择遍历方式,提高性能。

在JDK的源码中也有其它地方用到了这个特性。
比如Collections类中的binarySearch()方法

public static <T>
    int binarySearch(List<? extends Comparable<? super T>> list, T key) {
    	// 判断是否实现了RandomAccess 接口
        if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
            return Collections.indexedBinarySearch(list, key);
        else
            return Collections.iteratorBinarySearch(list, key);
    }

该方法中根据是否实现了RandomAccess 接口而采用不用的搜索方式。

private static <T>
    int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key) {
        int low = 0;
        int high = list.size()-1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            Comparable<? super T> midVal = list.get(mid);
            int cmp = midVal.compareTo(key);

            if (cmp < 0)
                low = mid + 1;
            else if (cmp > 0)
                high = mid - 1;
            else
                return mid; // key found
        }
        return -(low + 1);  // key not found
    }

在这里插入图片描述
在这里插入图片描述
总结:

  • RandomAccess接口支持快速随机访问。访问速度大于线性访问
  • 实现了RandomAccess接口的集合类,随机访问速度大于线性访问速度;未实现RandomAccess接口的集合类,线性访问速度大于随机访问速度
  • 集合类常用迭代器(Iterator)的方式实现线性访问
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值