Java中arraylist和linkedlist源代码分析与性能比較
Java中arraylist和linkedlist源代码分析与性能比較
1,简单介绍
在java开发中比較经常使用的数据结构是arraylist和linkedlist,本文主要从源代码角度分析arraylist和linkedlist的性能。
2,arraylist源代码分析
Arraylist底层的数据结构是一个对象数组。有一个size的成员变量标记数组中元素的个数,例如以下图:
- * The array buffer into which the elements of the ArrayList are stored.
- * The capacity of the ArrayList is the length of this array buffer.
- */
- private transient Object[] elementData;
- /**
- * The size of the ArrayList (the number of elements it contains).
- *
- * @serial
- */
- private int size;
在构造函数中Arraylist初始化为一个长度为10的对象数组。例如以下:
- /**
- * Constructs an empty list with the specified initial capacity.
- *
- * @param initialCapacity the initial capacity of the list
- * @throws IllegalArgumentException if the specified initial capacity
- * is negative
- */
- public ArrayList(int initialCapacity) {
- super();
- if (initialCapacity < 0)
- throw new IllegalArgumentException("Illegal Capacity: "+
- initialCapacity);
- this.elementData = new Object[initialCapacity];
- }
- /**
- * Constructs an empty list with an initial capacity of ten.
- */
- public ArrayList() {
- this(10);
- }
Arraylist在添加数据时,首先推断数组是否超过原始分配数组的长度。假设超过。则通过数组复制的形式扩大数组然后再添加数组元素。时间复杂度处于O(1)到O(n)之间。源代码例如以下:
- /**
- * Appends the specified element to the end of this list.
- *
- * @param e element to be appended to this list
- * @return <tt>true</tt> (as specified by {@link Collection#add})
- */
- public boolean add(E e) {
- ensureCapacityInternal(size + 1); // Increments modCount!!
- elementData[size++] = e;
- return true;
- }
- private void ensureCapacityInternal(int minCapacity) {
- modCount++;
- // overflow-conscious code
- if (minCapacity - elementData.length > 0)
- grow(minCapacity);
- }
- /**
- * Increases the capacity to ensure that it can hold at least the
- * number of elements specified by the minimum capacity argument.
- *
- * @param minCapacity the desired minimum capacity
- */
- private void grow(int minCapacity) {
- // overflow-conscious code
- int oldCapacity = elementData.length;
- int newCapacity = oldCapacity + (oldCapacity >> 1);
- if (newCapacity - minCapacity < 0)
- newCapacity = minCapacity;
- if (newCapacity - MAX_ARRAY_SIZE > 0)
- newCapacity = hugeCapacity(minCapacity);
- // minCapacity is usually close to size, so this is a win:
- elementData = Arrays.copyOf(elementData, newCapacity);
- }
Arraylist在删除数据时,首先会推断数组是否越界,然后会做一个数组从后向前复制的操作,时间复杂度是O(N),源代码例如以下图:
- /**
- * Removes the element at the specified position in this list.
- * Shifts any subsequent elements to the left (subtracts one from their
- * indices).
- *
- * @param index the index of the element to be removed
- * @return the element that was removed from the list
- * @throws IndexOutOfBoundsException {@inheritDoc}
- */
- public E remove(int index) {
- rangeCheck(index);
- modCount++;
- E oldValue = elementData(index);
- int numMoved = size - index - 1;
- if (numMoved > 0)
- System.arraycopy(elementData, index+1, elementData, index,
- numMoved);
- elementData[--size] = null; // Let gc do its work
- return oldValue;
- }
Arraylist在改动数据时,首先推断第i个元素是否越界,然后直接做赋值操作。时间复杂度是O(1)。
- /**
- * Replaces the element at the specified position in this list with
- * the specified element.
- *
- * @param index index of the element to replace
- * @param element element to be stored at the specified position
- * @return the element previously at the specified position
- * @throws IndexOutOfBoundsException {@inheritDoc}
- */
- public E set(int index, E element) {
- rangeCheck(index);
- E oldValue = elementData(index);
- elementData[index] = element;
- return oldValue;
- }
Arraylist在获取数据时,首先判读第i个元素是否越界,然后获取对象数组中的第i个元素时间复杂度是O(1)。源代码例如以下图:
- /**
- * Returns the element at the specified position in this list.
- *
- * @param index index of the element to return
- * @return the element at the specified position in this list
- * @throws IndexOutOfBoundsException {@inheritDoc}
- */
- public E get(int index) {
- rangeCheck(index);
- return elementData(index);
- }
3,linkedlist源代码分析
Linkedlist的用到的底层数据结构是双向链表,数据结构例如以下图:
- 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;
- }
- }
Linkedlist的成员变量主要有三个,size表示链表的长度,first指向链表的头部,last指向链表的尾部,源代码例如以下图:
- public class LinkedList<E>
- extends AbstractSequentialList<E>
- implements List<E>, Deque<E>, Cloneable, java.io.Serializable
- {
- transient int size = 0;
- /**
- * Pointer to first node.
- * Invariant: (first == null && last == null) ||
- * (first.prev == null && first.item != null)
- */
- transient Node<E> first;
- /**
- * Pointer to last node.
- * Invariant: (first == null && last == null) ||
- * (last.next == null && last.item != null)
- */
- transient Node<E> last;
Linkedlist的添加操作。仅仅是在链表的尾部添加一个节点,时间复杂度是O(1)。源代码例如以下图:
- /**
- * Appends the specified element to the end of this list.
- *
- * <p>This method is equivalent to {@link #addLast}.
- *
- * @param e element to be appended to this list
- * @return {@code true} (as specified by {@link Collection#add})
- */
- public boolean add(E e) {
- linkLast(e);
- return true;
- }
- /**
- * Links e as last element.
- */
- 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的删除操作。首先推断删除的位置是否越界。然后找到第i个元素,最后删除第一个元素,由于在删除的时候要依据元素的位置获取元素,所以时间复杂度是O(N)。源代码例如以下:
- /**
- * Removes the element at the specified position in this list. Shifts any
- * subsequent elements to the left (subtracts one from their indices).
- * Returns the element that was removed from the list.
- *
- * @param index the index of the element to be removed
- * @return the element previously at the specified position
- * @throws IndexOutOfBoundsException {@inheritDoc}
- */
- public E remove(int index) {
- checkElementIndex(index);
- return unlink(node(index));
- }
- </pre><pre code_snippet_id="1635127" snippet_file_name="blog_20160405_24_2093084" name="code" class="java"> /**
- * Returns the (non-null) Node at the specified element index.
- */
- Node<E> node(int index) {
- // assert isElementIndex(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;
- }
- }
- /**
- * Unlinks non-null node x.
- */
- E unlink(Node<E> x) {
- // assert x != null;
- final E element = x.item;
- final Node<E> next = x.next;
- final Node<E> prev = x.prev;
- if (prev == null) {
- first = next;
- } else {
- prev.next = next;
- x.prev = null;
- }
- if (next == null) {
- last = prev;
- } else {
- next.prev = prev;
- x.next = null;
- }
- x.item = null;
- size--;
- modCount++;
- return element;
- }
Linkedlist的改动操作。首先是推断数组是否越界。然后获取当前位置的元素。最后做改动操作,因为在获取当前位置的元素时,须要遍历链表。所以时间复杂度是O(N),源代码例如以下:
/**
- * Replaces the element at the specified position in this list with the
- * specified element.
- *
- * @param index index of the element to replace
- * @param element element to be stored at the specified position
- * @return the element previously at the specified position
- * @throws IndexOutOfBoundsException {@inheritDoc}
- */
- public E set(int index, E element) {
- checkElementIndex(index);
- Node<E> x = node(index);
- E oldVal = x.item;
- x.item = element;
- return oldVal;
- }
- /**
- * Returns the (non-null) Node at the specified element index.
- */
- Node<E> node(int index) {
- // assert isElementIndex(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的获取元素操作。首先是推断数组是否越界,然后获取当前位置的元素,因为在获取当前位置的元素时,须要遍历链表,所以时间复杂度是O(N),源代码例如以下:
- /**
- * Returns the element at the specified position in this list.
- *
- * @param index index of the element to return
- * @return the element at the specified position in this list
- * @throws IndexOutOfBoundsException {@inheritDoc}
- */
- public E get(int index) {
- checkElementIndex(index);
- return node(index).item;
- }
- /**
- * Returns the (non-null) Node at the specified element index.
- */
- Node<E> node(int index) {
- // assert isElementIndex(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;
- }
- }
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源代码分析与性能比較的更多相关文章
- Java中ArrayList与LinkedList的区别
Java中ArrayList与LinkedList的区别 一般大家都知道ArrayList和LinkedList的区别: 1. ArrayList的实现是基于数组,LinkedList的实现是基于双向 ...
- java中ArrayList 和 LinkedList 有什么区别
转: java中ArrayList 和 LinkedList 有什么区别 ArrayList和LinkedList都实现了List接口,有以下的不同点:1.ArrayList是基于索引的数据接口,它的 ...
- Java中ArrayList和LinkedList的性能分析
ArrayList和LinkedList是Java集合框架中经常使用的类.如果你只知道从基本性能比较ArrayList和LinkedList,那么请仔细阅读这篇文章. ArrayList应该在需要更多 ...
- Java中ArrayList和LinkedList差别
一般大家都知道ArrayList和LinkedList的大致差别: 1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构. 2.对于随机訪问get和set.A ...
- JAVA中ArrayList与LinkedList的区别以及对应List使用foreach与使用下标遍历的效率问题
近期在做一个对接京东的电商平台,所以对各个地方的效率考虑的比较多,今天深挖了一下ArrayList与LinkedList的区别以及对应List使用foreach与使用下标遍历的效率问题,首先说一下两种 ...
- Java中ArrayList和LinkedList区别 时间复杂度 与空间复杂度
一般大家都知道ArrayList和LinkedList的大致区别: 1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构. 2.对于随机访问 ...
- java中ArrayList、LinkedList、Vector的区别
ArrayList.LinkedList.Vector这三个类都实现了List接口. ArrayList是一个可以处理变长数组的类型,可以存放任意类型的对象.ArrayList的所有方法都是默认在单一 ...
- Java中ArrayList和LinkedList的异同
一:ArrayList和LinkedList的大致区别如下: 1.ArrayList是实现了基于动态数组的数据结构,ArrayList实现了长度可变的数组,在内存中分配连续的空间.遍历元素和随机访问元 ...
- Java中ArrayList和LinkedList区别
ArrayList和LinkedList的大致区别如下:1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构. 2.对于随机访问get和set,ArrayLis ...
随机推荐
- OpenERP财务管理若干概念讲解
来自:http://shine-it.net/index.php/topic,2431.0.html 一.记账凭证(Account Move) 会计上的记账凭证,也叫会计分录,在OpenERP中叫&q ...
- ubuntu执行级别,设置单用户模式
redhat的runlevel级别定义例如以下: 0:关机.不能将系统缺省执行级别设置为0,否则无法启动. 1:单用户模式.仅仅同意root用户对系统进行维护. 2:多用户模式.但不能使用NFS( ...
- jquery 获取css position的值
jquery 获取css position的值 CreateTime--2018年5月28日14:03:12 Author:Marydon 1.情景展示 <div id="aa&q ...
- getAttribure()和getParameter()的区别
1.getAttribute是取得jsp中 用setAttribute设定的attribute 2.parameter得到的是string:attribute得到的是object 3.request. ...
- CDH quick start VM 中运行wordcount例子
需要注意的事情: 1. 对于wordcount1.0 ,按照http://www.cloudera.com/content/cloudera/en/documentation/HadoopTutori ...
- react native window下的环境搭建和调试方案
这几天使用react native开发app,遇到一些坑,先记录下来,以后再继续补充 环境搭建 打开react native中文网,发现环境搭建特么也太复杂了,安装各种插件/软件,对于我们 编辑器+浏 ...
- EMQ学习---客户链接资源消耗
Erlang进程消耗EMQ对客户端链接使用链接进程(emqtt_client)和session进程(emqtt_session)分开的策略. 当一个mqtt的客户端连接到EMQ的服务器上的时候,首先会 ...
- ASP.NET给DataGrid,Repeater等添加全选批量删除等功能
很多情况下,在管理或者查看列表的时候我们需要很需要“全选”这个功能,这在ASP.NET中是非常容易实现的,下面我就将演示一点小代码实现这一功能. 实现全选的还是js的一个小函数: [code] ...
- jquery-osx
jQuery OSX https://github.com/jelly-liu/jquery-osx jquery-osx jquery, desktop, jquery desktop, jquer ...
- InnoDB存储引擎表的逻辑存储结构
1.索引组织表: 在InnoDB存储引擎中,表都是依照主键顺序组织存放的.这样的存储方式的表称为索引组织表,在innodb存储引擎表中,每张表都有主键.假设创建的时候没有显式定义主键,则Inn ...