对比ArrayList与LinkedList

不了解ArrayList的同学出门右转:ArrayList

了解过ArrayList之后但不了解LinkedList的同学就进来吧(嘿嘿)

简单理解LinkedList

在Java集合类中,除了使用最多的ArrayList,便是LinkedList,而这两个也是面试的重点,那么LinkedList究竟是什么样的呢?

编程语言的每个语法都有它深层次的含义,这次,我们还是看看它的源码来深入了解LinkedList。

我们还是先来看一下它的继承关系:

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable

可以看到,LinkedList实现了Deque和list接口。

壹·相关变量

    //容量
    transient int size = 0;

    /**
     *头节点
     *指向第一个节点的指针。
     * Invariant: (first == null && last == null) ||
     *            (first.prev == null && first.item != null)
     */
    transient Node<E> first;

    /**
     *尾节点
     * 指向最后一个节点的指针。
     * Invariant: (first == null && last == null) ||
     *            (last.next == null && last.item != null)
     */
    transient Node<E> last;

我们 ctrl + 点击 找到Node< E >,可以发现它是一个双向链表,具体源码如下:

    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源码:

//获得第index个节点的值
public E get(int index) {
	checkElementIndex(index);
	return node(index).item;
}
 
//设置第index元素的值
public E set(int index, E element) {
	checkElementIndex(index);
	Node<E> x = node(index);
	E oldVal = x.item;
	x.item = element;
	return oldVal;
}
 
//在index个节点之前添加新的节点
public void add(int index, E element) {
	checkPositionIndex(index);
 
	if (index == size)
		linkLast(element);
	else
		linkBefore(element, node(index));
}
 
//删除第index个节点
public E remove(int index) {
	checkElementIndex(index);
	return unlink(node(index));
}
 
//定位index处的节点
Node<E> node(int index) {
	// assert isElementIndex(index);
	//index<size/2时,从头开始找
	if (index < (size >> 1)) {
		Node<E> x = first;
		for (int i = 0; i < index; i++)
			x = x.next;
		return x;
	} else { //index>=size/2时,从尾开始找
		Node<E> x = last;
		for (int i = size - 1; i > index; i--)
			x = x.prev;
		return x;
	}
}

可以看出,LinkedList通过for循环进行查找,同时LinkedList也在查找方法上做了优化,比如index < size / 2,则从左边开始查找,反之从右边开始查找。

二者异同

还是先看一下他们两个的关系

可以看到他们两个都实现了list接口,可以说是好兄弟了,之所以功能不同是因为实现list接口方法的方式不一样(从这里也可以看出接口的好处,面向不同的业务需求就会有不同的是实现方式),List同时拥有Collection和Iterable的特性。

虽然是好兄弟,但是像现实中一样,肯定也有各自的特性,那下面我们就来讨论一下他们两个的异同。

壹·相同点

ArrayList基于动态数组实现,LinkedList基于双向链表,数组和链表都是线性表,对比于线性表的数据结构便是图和树。

贰·不同点

  • ArrayList是实现了基于动态数组的数据结构,而LinkedList是基于链表的数据结构
  • ArrayList存储方式为连续的,而LinkedList在物理逻辑上是不连续的(这个就是链表的特性了)
  • 对于随机访问get和set,ArrayList要优于LinkedList,因为LinkedList要移动指针,而ArrayList有索引index,在源码中可以看到,ArrayList想要get(int index)元素时,直接返回index位置上的元素,而LinkedList需要通过for循环进行查找,虽然已经优化,但效率肯定不及前者
  • 对于添加和删除操作add和remove,一般大家都会说LinkedList要比ArrayList快,因为ArrayList要移动数据。但是实际情况并非这样,对于添加或删除,LinkedList和ArrayList并不能明确说明谁快谁慢(实践是检验真理的唯一标准,感兴趣的同学可以自己写个程序体会一下)
    • 当插入的数据量很小时,两者区别不太大
    • 当插入的数据量大时,大约在容量的1/10之前,LinkedList会优于ArrayList
    • 在其后就劣与ArrayList,且越靠近后面越差

综上

所以一般首选用ArrayList,由于LinkedList可以实现栈、队列以及双端队列等数据结构,所以当特定需要时候,使用LinkedList,数据量小的时候,两者差不多,视具体情况去选择使用;当数据量大的时候,如果只需要在靠前的部分插入或删除数据,那也可以选用LinkedList,反之选择ArrayList效率更高。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值