我们都知道LinkedList和ArrayList相比:

  1、LinkedList插入删除相对较快,而查询较慢;

  2、ArrayList插入删除相对较慢,而查询很快(详细可查看从源码的角度分析List与Set的区别);

由类的关系可知,两者的顶层是一致的,但LinkedList额外的继承了AbstractSequentialList类并实现了Deque接口,也就是说LinkedList拥有双端 队列的功能,LinkedList的实现原理与ArrayList不同,LinkedList是链表的方式实现的

一、LinkedList插入删除相对较快,而查询较慢 LinkedList的add(E e)方法实际调用的是内部的linkLast(E e)方法,也就是添加到队列尾部

//每个元素在LinkedList中的存储结构,item为自身,prev为上一个节点,next为下一个节点
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev; Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
//添加元素
public boolean add(E e) {
linkLast(e);
return true;
}
//添加元素到链表尾部
void linkLast(E e) {
final Node<E> l = last;
//创建一个链表节点,上个元素为原有链表的最后一个元素,下一个元素为空
final Node<E> newNode = new Node<>(l, e, null);
//设置新的元素为链表最后一个元素
last = newNode;
//如果原来最后一个元素为空,则当前元素时第一个元素,给第一个元素的变量赋值
//如果原来的最后一个元素存在,则修改该元素的下一个元素为新的元素
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}

LinkedList的add(int index,E e)方法是在某个索引前插入元素E,先根据索引index找到相应元素,在该元素前添加新元素,添加方法与linkLast类似

//在指定位置插入元素
public void add(int index, E element) {
//校验索引是否有效,主要判断索引是否在size的范围内
checkPositionIndex(index);
//如果索引正好等于size,则添加到链表尾部,否则在指定位置插入新元素,修改原来该位置的元素的上级节点为新元素,新元素的上级元素为原有元素的上级元素
if (index == size)
linkLast(element);
else
//node(index)中主要是结合index和size循环找出原有index位置的元素
linkBefore(element, node(index));
}
//在某个节点前插入元素
void linkBefore(E e, Node<E> succ) {
// assert succ != null;
final Node<E> pred = succ.prev;
final Node<E> newNode = new Node<>(pred, e, succ);
succ.prev = newNode;
if (pred == null)
first = newNode;
else
pred.next = newNode;
size++;
modCount++;
}

addFirst、addLast等元素与以上实现类似,作用是添加元素到链表头、链表尾 移除元素remove(Object o)/remove(int index0)与插入类似

//移除元素
public boolean remove(Object o) {
//从第一个元素开始往下循环,找到第一个匹配到的元素移除
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null) {
//把当前元素的上个元素的next设置为当前元素的下一个元素,把当前元素的下一个节点的prev设置为当前元素的上一个元素,并把当前元素的prev、next、item都置为null以便于GC
unlink(x);
return true;
}
}
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item)) {
unlink(x);
return true;
}
}
}
return false;
}
//根据索引移除元素,先根据索引找出当前元素再进行移除
public E remove(int index) {
checkElementIndex(index);
return unlink(node(index));
}

根据以上可知,LinkedList的添加和移除等操作只对相应位置的上下元素进行改动即可,相对于ArrayList需要进行数组的复制移位性能要好些。而在查询来说,LinkedList需要根据索引以及内部存在的size、first、last进行循环匹配,相对于ArrayList只需要获取数组的相应下标所对应的值就会相应慢些。

//根据索引获取对象
public E get(int index) {
checkElementIndex(index);
return node(index).item;
}
//根据索引循环查询对应的元素
Node<E> node(int index) {
if (index < (size >> 1)) {
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else {
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}

LinkedList与ArrayList的区别的更多相关文章

  1. LinkedList和ArrayList的区别/何时使用LinkedList和ArrayList

    1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构. 2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList ...

  2. LinkedList和ArrayList的区别

    LinkedeList和ArrayList都实现了List接口,但是它们的工作原理却不一样.它们之间最主要的区别在于ArrayList是可改变大小的数组,而LinkedList是双向链接串列(doub ...

  3. Android LinkedList和ArrayList的区别

    LinkedeList和ArrayList都实现了List接口,但是它们的工作原理却不一样.它们之间最主要的区别在于ArrayList是可改变大小的数组,而LinkedList是双向链接串列(doub ...

  4. Java 中 LinkedList 和 ArrayList 的区别

    引自:https://www.cnblogs.com/huzi007/p/5550440.html ArrayList和LinkedList的大致区别如下:1.ArrayList是实现了基于动态数组的 ...

  5. LinkedList与ArrayList的区别(内部实现)

    ArrayList的内部实现是基于内部数组Object[],所以从概念上讲,它更像数组: LinkedList的内部实现是基于一组连接的记录,所以,它更像一个链表结构,所以,它们在性能上有很大的差别. ...

  6. Java ArrayList和Vector、LinkedList与ArrayList、数组(Array)和列表集合(ArrayList)的区别

    ArrayList和Vector的区别ArrayList与Vector主要从二方面来说.  一.同步性:   Vector是线程安全的,也就是说是同步的,而ArrayList是线程序不安全的,不是同步 ...

  7. 数组Array和列表集合ArrayList、LinkedList和Vector的区别

    一.ArrayList和Vector的区别 ArrayList与Vector主要从以下方面来说. 1.同步性: Vector是线程安全的,也就是说是同步的,而ArrayList是线程序不安全的,不是同 ...

  8. 集合中list、ArrayList、LinkedList、Vector的区别、Collection接口的共性方法以及数据结构的总结

    List (链表|线性表) 特点: 接口,可存放重复元素,元素存取是有序的,允许在指定位置插入元素,并通过索引来访问元素 1.创建一个用指定可视行数初始化的新滚动列表.默认情况下,不允许进行多项选择. ...

  9. java中List接口的实现类 ArrayList,LinkedList,Vector 的区别 list实现类源码分析

    java面试中经常被问到list常用的类以及内部实现机制,平时开发也经常用到list集合类,因此做一个源码级别的分析和比较之间的差异. 首先看一下List接口的的继承关系: list接口继承Colle ...

随机推荐

  1. PHP 5.3中的命名空间使用方法

    PHP的命名空间(namespace)是php5.3之后才有的.这个概念在C#中已经很早就有了,php中的namespace其实和c#的概念是一样的. 为什么php中要使用namespace? 假设如 ...

  2. Rails/ActiveRecord order by Array

    ActiveRecord中如果想根据自定义的一个数组id集合排序: ids = [2,1,3] users = User.where("id in (?)",ids) result ...

  3. 基于 CGLIB 库的动态代理机制

    之前的文章我们详细的介绍了 JDK 自身的 API 所提供的一种动态代理的实现,它的实现相对而言是简单的,但是却有一个非常致命性的缺陷,就是只能为接口中的方法完成代理,而委托类自己的方法或者父类中的方 ...

  4. Django 学习笔记(一) --- Hello Django

    人生苦短 ~ Tips:仅适用于 Python 3+(反正差别不大,py2 改改也能用).因为据 Python 之父 Guido van Rossum 说会在 2020 年停止对 Python 2 的 ...

  5. 【学习笔记】深入理解async/await

    参考资料:理解javaScript中的async/await,感谢原文作者的总结,本文在理解的基础上做了一点小小的修改,主要为了加深自己的知识点掌握 学完了Promise,我们知道可以用then链来解 ...

  6. LeetCode翻转矩阵后的得分-Python3<六>

    上一篇:LeetCode子域名访问计数-Python3.7<五> 题目:https://leetcode-cn.com/problems/score-after-flipping-matr ...

  7. Linux 系统性能分析工具 sar

    sar(System Activity Reporter系统活动情况报告)是目前 Linux 上最为全面的系统性能分析工具之一,可以 从多方面对系统的活动进行报告,包括:文件的读写情况.系统调用的使用 ...

  8. 让js中的函数只有一次有效调用的三种常用方法

    1.通过闭包来实现. <script> window.onload = function () { function once(fn) { var result; return funct ...

  9. 2017-12-05 JavaScript实现ZLOGO子集: 前进+转向

    在前文中文编程语言之Z语言初尝试: ZLOGO 4与相关讨论后, 萌生了用JavaScript编写类似语言以便在线编程的想法. 于是使用 @TKT2016 (知乎账号)的ZLOGO语法设计, 在编程语 ...

  10. 微信小程序顶部(navigationBar)设置为透明

    我记得在微信小程序中导航栏的颜色可以在app.json.  window里面添加navigationBarBackgroundColor属性,但是颜色只能为纯色.不能使用rgb,或者rgba的色号. ...