第8讲 对比Vector、 ArrayLis、 LinkedList有何区别?

对比Vector、 ArrayList、 LinkedList有何区别?

这三者都是实现集合框架中的List

Vector是Java早期提供的线程安全的动态数组,如果不需要线程安全,并不建议选择

ArrayList是应用更加广泛的动态数组实现,它本身不是线程安全的,所以性能要好很多。与Vector近似, ArrayList也是可以根据需要调整容量,不过两者的调整逻辑有所区别, Vector在扩容时会提高1倍,而ArrayList则是增加50%。

LinkedList是Java提供的双向链表,所以它不需要像上面两种那样调整容量,它也不是线程安全的。

image

Vector、 ArrayList、 LinkedList实现方式与应用场景中差别

1 底层实现方式

ArrayList内部用数组来实现; LinkedList内部采用双向链表实现; Vector内部用数组实现。

2 读写机制
ArrayList

插入元素

超过当前数组预定义的最大值时,数组需要扩容,扩容过程需要调用底层System.arraycopy()方法进行大量的数组复制操作;

    public void add(int index, E element) {
        rangeCheckForAdd(index);

        ensureCapacityInternal(size + 1);  // Increments modCount!!
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }

在删除元素时并不会减少数组的容量
(如果需要缩小数组容量,可以调用trimToSize()方法);

    /**
     * Trims the capacity of this <tt>ArrayList</tt> instance to be the
     * list's current size.  An application can use this operation to minimize
     * the storage of an <tt>ArrayList</tt> instance.
     */
    public void trimToSize() {
        modCount++;
        if (size < elementData.length) {
            elementData = (size == 0)
              ? EMPTY_ELEMENTDATA
              : Arrays.copyOf(elementData, size);
        }
    }

在查找元素时要遍历数组,对于非null的元素采取equals的方式寻找。

LinkedList
继承双端队列(Deque)
image
JDK1.8源码分析之LinkedList

在插入元素时,须创建一个新的Entry对象,并更新相应元素的前后元素的引用;

在查找元素时,需遍历链表;
在删除元素时,要遍历链表,找到要删除的元素,然后从链表上将此元素删除即可。

Vector与ArrayList仅在插入元素时容量扩充机制不一致。对于Vector,默认创建一个大小为10的Object数组,并将capacityIncrement设置为0;当插入元素数组大小不够时,如果capacityIncrement大于0,则将Object数组的大小扩大为现有size+capacityIncrement;如果capacityIncrement<=0,则将Object数组的大小扩大为现有大小的2倍。

浅谈ArrayList动态扩容

3 读写效率
  1. ArrayList基于数组实现。数组的特点就是连续内存存储,数组下标随机访问时间复杂度为O(1)。
  2. LinkedList基于双向链表实现。链表的特点是可以存储分散在内存中。

ArrayList添加元素,在没有扩容的情况下尾部插入并且制定初始容量,ArrayList的效率要高于LinkedList!!!

原因:虽然LinkedList不用循环查找元素,但是Linked在添加元素的时候多了new对象的操作。

4 线程安全性

ArrayList、 LinkedList为非线程安全; Vector是基于synchronized实现的线程安全的ArrayList。
需要注意的是:单线程应尽量使用ArrayList, Vector因为同步会有性能损耗;即使在多线程环境下,我们可以利用Collections这个类中为我们提供的synchronizedList(List list)方法返回一个
线程安全的同步列表对象。

5 关于LinkedList迭代遍历

LinkedList在迭代遍历的时候,不要使用fori循环遍历!!!

for循环遍历get (i)的时候,会根据i的值,算出是在这个链表的前一半还是后一半,前一半正序遍历,后一半倒序遍历。

那么例如在get(2)的时候,先找到0位置的node,再去找到下一位的Node 1.再去找到下一位的node 2。会查找3次。而 arrayList只会查找一次。

To Java程序员:切勿用普通for循环遍历LinkedList

参考:
极客时间:《Java核心技术面试精讲》

本笔记根据专栏主题进行学习笔记,虽然参考了许多做了笔记,但是加上了自己的整理,跟原作者的行文可能有很大偏差。如果想查看原版请自行搜索。谢谢

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值