点击上方“方志朋”,选择“设为星标”

回复”666“获取新整理的面试文章

来源 | http://t.cn/AilfR3YW

在我们的开发中,List接口是最常见不过,而且我们几乎每天都在用ArrayList或者LinkedList,但是细心的同学有没有发现,ArrayList中实现了RandomAccess接口,而LinkedList却没有实现RandomAccess接口,这是为什么呢?

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

RandomAccess接口中是空的,RandomAccess接口又是什么呢?

public interface RandomAccess {
}

RandomAccess接口

RandomAccess是一个标记接口,官方解释是只要List实现这个接口,就能支持快速随机访问。而什么是随机访问呢?接下来我们来举例说明。

Collections是集合的一个工具类,我们看一下Collections源码中的二分搜索方法。

public static <T>int binarySearch(List<? extends Comparable<? super T>> list, T key) {if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)return Collections.indexedBinarySearch(list, key);elsereturn Collections.iteratorBinarySearch(list, key);}

在源码中可以看出,判断list是否是RandomAccess的实例,如果是,则执行indexedBinarySearch方法,如果不是,则执行iteratorBinarySearch方法。接下来看一下这两个方法。

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;elsereturn mid; // key found}return -(low + 1);  // key not found
}
private static <T>
int iteratorBinarySearch(List<? extends Comparable<? super T>> list, T key)
{int low = 0;int high = list.size()-1;ListIterator<? extends Comparable<? super T>> i = list.listIterator();while (low <= high) {int mid = (low + high) >>> 1;Comparable<? super T> midVal = get(i, mid);int cmp = midVal.compareTo(key);if (cmp < 0)low = mid + 1;else if (cmp > 0)high = mid - 1;elsereturn mid; // key found}return -(low + 1);  // key not found
}

上述两个方法的源码表示,实现了RandomAccess接口的List使用索引遍历,而未实现RandomAccess接口的List使用迭代器遍历。那么为什么要这么设计呢?
既然涉及到二分搜索的遍历操作,那么现在我们来分析一下ArrayList和LinkedList遍历元素的性能如何?

public class CollectionTest {public static void main(String[] args){long arrayListIndexedTime = arrayListIndexed();long arrayListIteratorTime = arrayListIterator();long linkedListIndexedTime = linkedListIndexed();long linkedListIteratorTime = linkedListIterator();System.out.println("测试ArrayList通过for遍历所消耗时间:" + arrayListIndexedTime);System.out.println("测试ArrayList通过iterator遍历所消耗时间:" + arrayListIteratorTime);System.out.println("测试LinkedList通过for遍历所消耗时间:" + linkedListIndexedTime);System.out.println("测试LinkedList通过iterator遍历所消耗时间:" + linkedListIteratorTime);}//测试ArrayList通过for遍历所消耗时间public static long arrayListIndexed() {List<Integer> arrayList = new ArrayList<>();for (int i = 0; i < 10000; i++) {arrayList.add(i);}//记录开始时间long startTime = System.currentTimeMillis();for (int i = 0; i < arrayList.size(); i++) {arrayList.get(i);}//记录结束时间long endTime = System.currentTimeMillis();//遍历消耗时间long resultTime = endTime - startTime;return resultTime;}//测试ArrayList通过iterator遍历所消耗时间public static long arrayListIterator() {List<Integer> arrayList = new ArrayList<>();for (int i = 0; i < 10000; i++) {arrayList.add(i);}//记录开始时间long startTime = System.currentTimeMillis();Iterator<Integer> iterator = arrayList.iterator();while (iterator.hasNext()) {iterator.next();}//记录结束时间long endTime = System.currentTimeMillis();//遍历消耗时间long resultTime = endTime - startTime;return resultTime;}//测试LinkedList通过for遍历所消耗时间public static long linkedListIndexed() {List<Integer> linkedList = new LinkedList<>();for (int i = 0; i < 10000; i++) {linkedList.add(i);}//记录开始时间long startTime = System.currentTimeMillis();for (int i = 0; i < linkedList.size(); i++) {linkedList.get(i);}//记录结束时间long endTime = System.currentTimeMillis();//遍历消耗时间long resultTime = endTime - startTime;return resultTime;}//测试LinkedList通过iterator遍历所消耗时间public static long linkedListIterator() {List<Integer> linkedList = new LinkedList<>();for (int i = 0; i < 10000; i++) {linkedList.add(i);}//记录开始时间long startTime = System.currentTimeMillis();Iterator<Integer> iterator = linkedList.iterator();while (iterator.hasNext()) {iterator.next();}//记录结束时间long endTime = System.currentTimeMillis();//遍历消耗时间long resultTime = endTime - startTime;return resultTime;}
}

测试结果如下

测试ArrayList通过for遍历所消耗时间:1
测试ArrayList通过iterator遍历所消耗时间:2
测试LinkedList通过for遍历所消耗时间:47
测试LinkedList通过iterator遍历所消耗时间:1

我们来分析一下测试结果:ArrayList通过for遍历比通过iterator遍历要稍快,LinkedList通过iterator遍历比通过for遍历要快。

所以说在我们的应用中,要考虑使用List接口的哪种实现类,可以更好更高效的满足实际场景需求。所以在这里通过实现RandomAccess接口来区分List的哪种实现类。

总结

最后总结一句话:实现RandomAccess接口的List可以通过for循环来遍历数据比使用iterator遍历数据更高效,未实现RandomAccess接口的List可以通过iterator遍历数据比使用for循环来遍历数据更高效。

热门内容:Java8 快速实现List转map 、分组、过滤等操作
SpringBoot 三招组合拳,手把手教你打出优雅的后端接口不要再自己封装各种Util工具类了,这款神仙级框架你值得拥有!实战:上亿数据如何秒查真牛逼!我司用了7年的分布式锁方案...最近面试BAT,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。
明天见(。・ω・。)ノ

ArrayList 为什么要实现 RandomAccess 接口?相关推荐

  1. Java ArrayList 为什么要实现 RandomAccess 接口?

    在我们的开发中,List接口是最常见不过,而且我们几乎每天都在用ArrayList或者LinkedList,但是细心的同学有没有发现,ArrayList中实现了RandomAccess接口,而Link ...

  2. 【Java】ArrayList 为啥要实现 RandomAccess 接口

    1.概述 转载:http://www.javastack.cn/article/2019/why-arraylist-impl-randomaccess-interface/ 在我们的开发中,List ...

  3. ArrayList集合类实现的RandomAccess空接口有何用?

    相信不少小伙伴在查看 ArrayList 集合时发现该集合类实现了一个 RandomAccess 空实现的接口,源码如下 ⬇️ ArrayList 源码: RandomAccess 接口源码: 可以看 ...

  4. ArrayList集合实现RandomAccess接口有何作用?为何LinkedList集合却没实现这接口?

    众所周知,在List集合中,我们经常会用到ArrayList以及LinkedList集合,但是通过查看源码,就会发现ArrayList实现RandomAccess接口,但是RandomAccess接口 ...

  5. 重要接口—RandomAccess接口

    原文作者:志波同学 原文地址:Java编程:RandomAccess接口 目录 一.随机访问和串行访问 二.快速随机访问 RandomAccess 是一个标记接口,标识实现该接口的类支持快速随机访问. ...

  6. RandomAccess接口

    RandomAccess是一个标记接口,实现该接口表示支持快速访问.这是一个空接口,没有任何方法. 当实现该接口时,说明支持快速访问. 即: for (int i=0, n=list.size(); ...

  7. 开课吧之Java常见面试题之RandomAccess接口

    RandomAccess接口?* 查看源码我们发现实际上 RandomAccess 接口中什么都没有定义.所以,在我看来 RandomAccess 接口不过是一个标识罢了.标识什么? 标识实现这个接口 ...

  8. RandomAccess接口使用

    引子:   RandomAccess在类Collections的shuffle()方法中的使用:(jdk源码如下) Java代码   <span style="font-size: s ...

  9. RandomAccess接口详解

    RandomAccess接口详解 Interface RandomAccess All Known Implementing Classes: ArrayList, AttributeList, Co ...

最新文章

  1. 查看 Android SDK Build-tools 版本号
  2. MAT之ACA:利用ACA解决TSP优化最佳路径问题
  3. SBO业务单据类型(总结)
  4. 编程之性能优化知多少
  5. 陕西科技大学18计算机调剂,2018年陕西科技大学考研调剂信息公布
  6. [渝粤教育] 西南科技大学 经济数学1 在线考试复习资料
  7. Tecplot中如何提取水线面(自由表面)并绘图
  8. UVA 10891 SUM游戏 DP
  9. WebMaster如何处理网站内容重复?
  10. 机器学习基础(五十五)—— 核(Kernel Trick)
  11. 【ubuntu操作系统入门】Ubuntu常用命令大全二
  12. c语言源代码三角函数大全,【C语言及程序设计】项目2-9-3:编制三角函数表
  13. mac os监听扬声器、麦克风的音量、静音
  14. 全球及中国建筑弹性体行业发展形势及竞争前景调研报告2022-2027年
  15. 隐藏index.php
  16. we learn考试能切屏吗_螺蛳粉闻臭师年薪50万,你想挑战吗?
  17. Python爬虫实战 | (3) 爬取豆瓣电影Top250
  18. 小鱼赚钱app是真的吗?小鱼赚钱下载试玩应用教程
  19. 【渝粤题库】陕西师范大学292221 保险学Ⅰ 作业(高起专)
  20. 酷比魔方iwork12 linux,用KB3195781累集更新补丁1511变1903的酷比魔方iwork12Windows10系统...

热门文章

  1. java内存泄漏问题排查
  2. 《DSP using MATLAB》Problem 5.7
  3. bzoj1070————2016——3——14
  4. 结对项目开发电梯调度 - 整体设计
  5. rwkj 1422搜索(素数环)
  6. C#做外挂常用API
  7. GridView 始终显示 Pager 分页行的一种方法
  8. Scratch青少年编程能力等级测试模拟题(一级)
  9. 【MATLAB】雅可比矩阵jacobi matrix
  10. 3000 字推荐一个可视化神器,50 行 Python 代码制作数据大屏