前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ArrayList 与 LinkedList 区别

ArrayList 与 LinkedList 区别

作者头像
happyJared
发布2019-06-15 15:13:43
8080
发布2019-06-15 15:13:43
举报
文章被收录于专栏:happyJaredhappyJared
  1. 是否线程安全:都是不同步的,也就是不保证线程安全;
  2. 底层数据结构:ArrayList 底层使用的是 Object[] 数组;LinkedList 使用的是双向链表数据结构(JDK1.6前为双向循环链表,JDK1.7后取消了循环);
  3. 插入删除影响:① ArrayList 采用数组存储,因此插入和删除元素的时间复杂度都受元素位置的影响。比如:执行 add(E e) 方法的时候, ArrayList 会默认将该元素追加到此列表的末尾,这种情况的时间复杂度就是 O(1)。但是如果要在指定位置 i 插入和删除元素的话(add(int index, E element)),那么时间复杂度就为 O(n-i),因为在进行上述操作的时候,集合中第 i 和第 i 个元素之后的 (n-i) 个元素,都要执行向后/前位移一位的操作。 ② LinkedList 采用的是链表存储,所以插入、删除元素时间复杂度不受元素位置的影响,都是近似 O(1),而数组为近似 O(n);
  4. 快速随机访问: LinkedList 不支持高效的随机元素访问,而 ArrayList 支持,所谓快速随机访问,是通过元素的序号来定位元素对象 (对应get(int index)方法);
  5. 内存空间占用: ArrayList 的空间浪费,主要体现在 List 列表的结尾,会预留一定的空间容量;而 LinkedList 的空间花费,则体现在它的每一个元素,都需要消耗比 ArrayList 更多的空间,这是由于直接后继和直接前驱的存在。
关于 RandomAccess 接口
代码语言:javascript
复制
public interface RandomAccess {
}

查看源码可以看到, RandomAccess 接口中什么都没有定义。所以,这就是个标识接口,标识那些实现了这个接口的类,具有随机访问的功能。

binarySearch() 方法中,它要判断传入的 List 是否是 RamdomAccess 的实例。如果是,则调用 indexedBinarySearch() 方法;如果不是,那么就调用 iteratorBinarySearch() 方法

代码语言:javascript
复制
    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);
        else
            return Collections.iteratorBinarySearch(list, key);
    }

ArrayList 实现了 RandomAccess 接口, 而 LinkedList 没有实现。为什么呢?还是和底层数据结构有关。ArrayList 底层是数组,而 LinkedList 底层是链表。数组天然支持随机访问,时间复杂度为 O(1),所以支持快速随机访问。而链表需要遍历到特定的位置,才能访问特定位置的元素,时间复杂度为 O(n),所以不是快速高效的随机访问。

ArrayList 实现了 RandomAccess 接口,表明了具有快速随机访问的功能。不过 RandomAccess 接口只是一个标识,并不是说 ArrayList 实现 RandomAccess 接口,才具有快速随机访问的功能!

总结 List 的遍历方式选择:

  • 实现了 RandomAccess 接口的 list,优先选择普通 for 循环 ,其次 foreach;
  • 未实现 RandomAccess 接口的 ist, 优先选择 iterator 遍历(foreach 遍历底层也是通过 iterator 实现的),大 size 的数据,千万不要使用普通 for 循环。
关于双向链表和双向循环链表

双向链表

双向链表: 包含两个指针,一个 prev 指针指向前一个节点(第一个 prev 指向 nil),一个 next 指针指向后一个节点(最后一个 next 同样指向 nil);

双向循环链表: 最后一个节点的 next 指针指向第一个节点的 head,而第一个节点的 head 的 prev 指针指向最后一个节点,所以是构成一个循环。

双向循环链表

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.06.13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 关于 RandomAccess 接口
  • 关于双向链表和双向循环链表
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档