Java中arraylist和linkedlist源代码分析与性能比較

1,简单介绍

在java开发中比較经常使用的数据结构是arraylist和linkedlist,本文主要从源代码角度分析arraylist和linkedlist的性能。

2,arraylist源代码分析

Arraylist底层的数据结构是一个对象数组。有一个size的成员变量标记数组中元素的个数,例如以下图:

  1. * The array buffer into which the elements of the ArrayList are stored.
  2. * The capacity of the ArrayList is the length of this array buffer.
  3. */
  4. private transient Object[] elementData;
  5.  
  6. /**
  7. * The size of the ArrayList (the number of elements it contains).
  8. *
  9. * @serial
  10. */
  11. private int size;

在构造函数中Arraylist初始化为一个长度为10的对象数组。例如以下:

  1. /**
  2. * Constructs an empty list with the specified initial capacity.
  3. *
  4. * @param initialCapacity the initial capacity of the list
  5. * @throws IllegalArgumentException if the specified initial capacity
  6. * is negative
  7. */
  1. public ArrayList(int initialCapacity) {
  2. super();
  3. if (initialCapacity < 0)
  4. throw new IllegalArgumentException("Illegal Capacity: "+
  5. initialCapacity);
  6. this.elementData = new Object[initialCapacity];
  7. }
  1. /**
  2. * Constructs an empty list with an initial capacity of ten.
  3. */
  4. public ArrayList() {
  5. this(10);
  6. }

Arraylist在添加数据时,首先推断数组是否超过原始分配数组的长度。假设超过。则通过数组复制的形式扩大数组然后再添加数组元素。时间复杂度处于O(1)到O(n)之间。源代码例如以下:

  1. /**
  2. * Appends the specified element to the end of this list.
  3. *
  4. * @param e element to be appended to this list
  5. * @return <tt>true</tt> (as specified by {@link Collection#add})
  6. */
  7. public boolean add(E e) {
  8. ensureCapacityInternal(size + 1); // Increments modCount!!
  9. elementData[size++] = e;
  10. return true;
  11. }

  1. private void ensureCapacityInternal(int minCapacity) {
  2. modCount++;
  3. // overflow-conscious code
  4. if (minCapacity - elementData.length > 0)
  5. grow(minCapacity);
  6. }

  1. /**
  2. * Increases the capacity to ensure that it can hold at least the
  3. * number of elements specified by the minimum capacity argument.
  4. *
  5. * @param minCapacity the desired minimum capacity
  6. */
  7. private void grow(int minCapacity) {
  8. // overflow-conscious code
  9. int oldCapacity = elementData.length;
  10. int newCapacity = oldCapacity + (oldCapacity >> 1);
  11. if (newCapacity - minCapacity < 0)
  12. newCapacity = minCapacity;
  13. if (newCapacity - MAX_ARRAY_SIZE > 0)
  14. newCapacity = hugeCapacity(minCapacity);
  15. // minCapacity is usually close to size, so this is a win:
  16. elementData = Arrays.copyOf(elementData, newCapacity);
  17. }

Arraylist在删除数据时,首先会推断数组是否越界,然后会做一个数组从后向前复制的操作,时间复杂度是O(N),源代码例如以下图:

  1. /**
  2. * Removes the element at the specified position in this list.
  3. * Shifts any subsequent elements to the left (subtracts one from their
  4. * indices).
  5. *
  6. * @param index the index of the element to be removed
  7. * @return the element that was removed from the list
  8. * @throws IndexOutOfBoundsException {@inheritDoc}
  9. */
  10. public E remove(int index) {
  11. rangeCheck(index);
  12.  
  13. modCount++;
  14. E oldValue = elementData(index);
  15.  
  16. int numMoved = size - index - 1;
  17. if (numMoved > 0)
  18. System.arraycopy(elementData, index+1, elementData, index,
  19. numMoved);
  20. elementData[--size] = null; // Let gc do its work
  21.  
  22. return oldValue;
  23. }

Arraylist在改动数据时,首先推断第i个元素是否越界,然后直接做赋值操作。时间复杂度是O(1)。

  1. /**
  2. * Replaces the element at the specified position in this list with
  3. * the specified element.
  4. *
  5. * @param index index of the element to replace
  6. * @param element element to be stored at the specified position
  7. * @return the element previously at the specified position
  8. * @throws IndexOutOfBoundsException {@inheritDoc}
  9. */
  10. public E set(int index, E element) {
  11. rangeCheck(index);
  12.  
  13. E oldValue = elementData(index);
  14. elementData[index] = element;
  15. return oldValue;
  16. }

Arraylist在获取数据时,首先判读第i个元素是否越界,然后获取对象数组中的第i个元素时间复杂度是O(1)。源代码例如以下图:

  1. /**
  2. * Returns the element at the specified position in this list.
  3. *
  4. * @param index index of the element to return
  5. * @return the element at the specified position in this list
  6. * @throws IndexOutOfBoundsException {@inheritDoc}
  7. */
  8. public E get(int index) {
  9. rangeCheck(index);
  10.  
  11. return elementData(index);
  12. }

3,linkedlist源代码分析

Linkedlist的用到的底层数据结构是双向链表,数据结构例如以下图:

  1. private static class Node<E> {
  2. E item;
  3. Node<E> next;
  4. Node<E> prev;
  5.  
  6. Node(Node<E> prev, E element, Node<E> next) {
  7. this.item = element;
  8. this.next = next;
  9. this.prev = prev;
  10. }
  11. }

Linkedlist的成员变量主要有三个,size表示链表的长度,first指向链表的头部,last指向链表的尾部,源代码例如以下图:

  1. public class LinkedList<E>
  2. extends AbstractSequentialList<E>
  3. implements List<E>, Deque<E>, Cloneable, java.io.Serializable
  4. {
  5. transient int size = 0;
  6.  
  7. /**
  8. * Pointer to first node.
  9. * Invariant: (first == null && last == null) ||
  10. * (first.prev == null && first.item != null)
  11. */
  12. transient Node<E> first;
  13.  
  14. /**
  15. * Pointer to last node.
  16. * Invariant: (first == null && last == null) ||
  17. * (last.next == null && last.item != null)
  18. */
  19. transient Node<E> last;

Linkedlist的添加操作。仅仅是在链表的尾部添加一个节点,时间复杂度是O(1)。源代码例如以下图:

  1. /**
  2. * Appends the specified element to the end of this list.
  3. *
  4. * <p>This method is equivalent to {@link #addLast}.
  5. *
  6. * @param e element to be appended to this list
  7. * @return {@code true} (as specified by {@link Collection#add})
  8. */
  9. public boolean add(E e) {
  10. linkLast(e);
  11. return true;
  12. }
  1. /**
  2. * Links e as last element.
  3. */
  4. void linkLast(E e) {
  5. final Node<E> l = last;
  6. final Node<E> newNode = new Node<>(l, e, null);
  7. last = newNode;
  8. if (l == null)
  9. first = newNode;
  10. else
  11. l.next = newNode;
  12. size++;
  13. modCount++;
  14. }

Linkedlist的删除操作。首先推断删除的位置是否越界。然后找到第i个元素,最后删除第一个元素,由于在删除的时候要依据元素的位置获取元素,所以时间复杂度是O(N)。源代码例如以下:

  1. /**
  2. * Removes the element at the specified position in this list. Shifts any
  3. * subsequent elements to the left (subtracts one from their indices).
  4. * Returns the element that was removed from the list.
  5. *
  6. * @param index the index of the element to be removed
  7. * @return the element previously at the specified position
  8. * @throws IndexOutOfBoundsException {@inheritDoc}
  9. */
  10. public E remove(int index) {
  11. checkElementIndex(index);
  12. return unlink(node(index));
  13. }
  1. </pre><pre code_snippet_id="1635127" snippet_file_name="blog_20160405_24_2093084" name="code" class="java"> /**
  2. * Returns the (non-null) Node at the specified element index.
  3. */
  4. Node<E> node(int index) {
  5. // assert isElementIndex(index);
  6.  
  7. if (index < (size >> 1)) {
  8. Node<E> x = first;
  9. for (int i = 0; i < index; i++)
  10. x = x.next;
  11. return x;
  12. } else {
  13. Node<E> x = last;
  14. for (int i = size - 1; i > index; i--)
  15. x = x.prev;
  16. return x;
  17. }
  18. }
  1. /**
  2. * Unlinks non-null node x.
  3. */
  4. E unlink(Node<E> x) {
  5. // assert x != null;
  6. final E element = x.item;
  7. final Node<E> next = x.next;
  8. final Node<E> prev = x.prev;
  9.  
  10. if (prev == null) {
  11. first = next;
  12. } else {
  13. prev.next = next;
  14. x.prev = null;
  15. }
  16.  
  17. if (next == null) {
  18. last = prev;
  19. } else {
  20. next.prev = prev;
  21. x.next = null;
  22. }
  23.  
  24. x.item = null;
  25. size--;
  26. modCount++;
  27. return element;
  28. }

Linkedlist的改动操作。首先是推断数组是否越界。然后获取当前位置的元素。最后做改动操作,因为在获取当前位置的元素时,须要遍历链表。所以时间复杂度是O(N),源代码例如以下:

/**

  1. * Replaces the element at the specified position in this list with the
  2. * specified element.
  3. *
  4. * @param index index of the element to replace
  5. * @param element element to be stored at the specified position
  6. * @return the element previously at the specified position
  7. * @throws IndexOutOfBoundsException {@inheritDoc}
  8. */
  9. public E set(int index, E element) {
  10. checkElementIndex(index);
  11. Node<E> x = node(index);
  12. E oldVal = x.item;
  13. x.item = element;
  14. return oldVal;
  15. }
  1. /**
  2. * Returns the (non-null) Node at the specified element index.
  3. */
  4. Node<E> node(int index) {
  5. // assert isElementIndex(index);
  6.  
  7. if (index < (size >> 1)) {
  8. Node<E> x = first;
  9. for (int i = 0; i < index; i++)
  10. x = x.next;
  11. return x;
  12. } else {
  13. Node<E> x = last;
  14. for (int i = size - 1; i > index; i--)
  15. x = x.prev;
  16. return x;
  17. }
  18. }

Linkedlist的获取元素操作。首先是推断数组是否越界,然后获取当前位置的元素,因为在获取当前位置的元素时,须要遍历链表,所以时间复杂度是O(N),源代码例如以下:

  1. /**
  2. * Returns the element at the specified position in this list.
  3. *
  4. * @param index index of the element to return
  5. * @return the element at the specified position in this list
  6. * @throws IndexOutOfBoundsException {@inheritDoc}
  7. */
  8. public E get(int index) {
  9. checkElementIndex(index);
  10. return node(index).item;
  11. }
  1. /**
  2. * Returns the (non-null) Node at the specified element index.
  3. */
  4. Node<E> node(int index) {
  5. // assert isElementIndex(index);
  6.  
  7. if (index < (size >> 1)) {
  8. Node<E> x = first;
  9. for (int i = 0; i < index; i++)
  10. x = x.next;
  11. return x;
  12. } else {
  13. Node<E> x = last;
  14. for (int i = size - 1; i > index; i--)
  15. x = x.prev;
  16. return x;
  17. }
  18. }

4。arraylist和linkedlist的效率分析

Add()

Remove(int i)

Set(int i, E e)

Get(int i)

Arraylist

O(1)-O(N)

O(N)

O(1)

O(1)

Linkedlist

O(1)

O(N)

O(N)

O(N)



Java中arraylist和linkedlist源代码分析与性能比較的更多相关文章

  1. Java中ArrayList与LinkedList的区别

    Java中ArrayList与LinkedList的区别 一般大家都知道ArrayList和LinkedList的区别: 1. ArrayList的实现是基于数组,LinkedList的实现是基于双向 ...

  2. java中ArrayList 和 LinkedList 有什么区别

    转: java中ArrayList 和 LinkedList 有什么区别 ArrayList和LinkedList都实现了List接口,有以下的不同点:1.ArrayList是基于索引的数据接口,它的 ...

  3. Java中ArrayList和LinkedList的性能分析

    ArrayList和LinkedList是Java集合框架中经常使用的类.如果你只知道从基本性能比较ArrayList和LinkedList,那么请仔细阅读这篇文章. ArrayList应该在需要更多 ...

  4. Java中ArrayList和LinkedList差别

    一般大家都知道ArrayList和LinkedList的大致差别: 1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构.  2.对于随机訪问get和set.A ...

  5. JAVA中ArrayList与LinkedList的区别以及对应List使用foreach与使用下标遍历的效率问题

    近期在做一个对接京东的电商平台,所以对各个地方的效率考虑的比较多,今天深挖了一下ArrayList与LinkedList的区别以及对应List使用foreach与使用下标遍历的效率问题,首先说一下两种 ...

  6. Java中ArrayList和LinkedList区别 时间复杂度 与空间复杂度

    一般大家都知道ArrayList和LinkedList的大致区别:      1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构.      2.对于随机访问 ...

  7. java中ArrayList、LinkedList、Vector的区别

    ArrayList.LinkedList.Vector这三个类都实现了List接口. ArrayList是一个可以处理变长数组的类型,可以存放任意类型的对象.ArrayList的所有方法都是默认在单一 ...

  8. Java中ArrayList和LinkedList的异同

    一:ArrayList和LinkedList的大致区别如下: 1.ArrayList是实现了基于动态数组的数据结构,ArrayList实现了长度可变的数组,在内存中分配连续的空间.遍历元素和随机访问元 ...

  9. Java中ArrayList和LinkedList区别

    ArrayList和LinkedList的大致区别如下:1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构. 2.对于随机访问get和set,ArrayLis ...

随机推荐

  1. OpenERP财务管理若干概念讲解

    来自:http://shine-it.net/index.php/topic,2431.0.html 一.记账凭证(Account Move) 会计上的记账凭证,也叫会计分录,在OpenERP中叫&q ...

  2. ubuntu执行级别,设置单用户模式

    redhat的runlevel级别定义例如以下:   0:关机.不能将系统缺省执行级别设置为0,否则无法启动. 1:单用户模式.仅仅同意root用户对系统进行维护. 2:多用户模式.但不能使用NFS( ...

  3. jquery 获取css position的值

      jquery 获取css position的值 CreateTime--2018年5月28日14:03:12 Author:Marydon 1.情景展示 <div id="aa&q ...

  4. getAttribure()和getParameter()的区别

    1.getAttribute是取得jsp中 用setAttribute设定的attribute 2.parameter得到的是string:attribute得到的是object 3.request. ...

  5. CDH quick start VM 中运行wordcount例子

    需要注意的事情: 1. 对于wordcount1.0 ,按照http://www.cloudera.com/content/cloudera/en/documentation/HadoopTutori ...

  6. react native window下的环境搭建和调试方案

    这几天使用react native开发app,遇到一些坑,先记录下来,以后再继续补充 环境搭建 打开react native中文网,发现环境搭建特么也太复杂了,安装各种插件/软件,对于我们 编辑器+浏 ...

  7. EMQ学习---客户链接资源消耗

    Erlang进程消耗EMQ对客户端链接使用链接进程(emqtt_client)和session进程(emqtt_session)分开的策略. 当一个mqtt的客户端连接到EMQ的服务器上的时候,首先会 ...

  8. ASP.NET给DataGrid,Repeater等添加全选批量删除等功能

    很多情况下,在管理或者查看列表的时候我们需要很需要“全选”这个功能,这在ASP.NET中是非常容易实现的,下面我就将演示一点小代码实现这一功能.   实现全选的还是js的一个小函数:   [code] ...

  9. jquery-osx

    jQuery OSX https://github.com/jelly-liu/jquery-osx jquery-osx jquery, desktop, jquery desktop, jquer ...

  10. InnoDB存储引擎表的逻辑存储结构

    1.索引组织表:     在InnoDB存储引擎中,表都是依照主键顺序组织存放的.这样的存储方式的表称为索引组织表,在innodb存储引擎表中,每张表都有主键.假设创建的时候没有显式定义主键,则Inn ...