Vector、ArrayList、LinkedList的区别

这篇博客探讨了Java中Vector、ArrayList和LinkedList的区别,它们都是List接口的实现。Vector是线程安全但效率较低的动态数组,ArrayList是非线程安全但性能更好的动态数组,而LinkedList是高效的双向链表。不同容器适用于不同的场景,如ArrayList适合随机访问,LinkedList适合频繁插入和删除。文章还简单分析了ArrayList的add(E e)方法和扩容机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


Vector、ArrayList、LinkedList的区别

这三者都是实现集合框架中的List,也就是所谓的有序集合

Vector是Java早期提供的线程安全的动态数组,如果不需要线程安全,并不建议选择,毕竟同步是有额外开销的。Vector内部是使用对象数组来保存数据,可以根据需要自动的增加容量,当数组已满时,会创建新的数组,并拷贝原有数组数据。

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

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

ArrayListVectorLinkedList
底层实现方式Object数组Vector是基于synchronized实现的线程安全的ArrayList.
Vector在扩容时会提高一倍,而ArrayList则是增加50%
双向循环链表(JDK1.6之前)
双向链表(JDK1.7取消了循环)
读写机制插入:超过当前数组预定义的最大值时,数组需要扩容,扩容过程需要调用底层System.arraycopy()方法进行数组复制操作
删:删除元素时并不会减少数组的容量,如需缩小容量,可调用trimToSize()方法,在查找元素时要遍历数组,对非null的元素采取equals的方式查找
插入:须创建一个新的Entry对象,并更新相应元素的前后元素的引用
在查找元素时,需遍历链表
在删除元素时,要遍历链表,找到要删除的元素,然后从链表上将此元素删除
读写效率ArrayList对元素的增加和删除都会引起数组的内存分配空间动态发生变化,对其进行插入和删除速度较慢,但检索速度快LinkedList由于基于链表方式存放数据,增加和删除元素的速度较快,但检索速度较慢
线程安全性非线程安全非线程安全

不同容器类型适合的应用场景

  • Vector和ArrayList作为动态数组,其内部元素以数组形式顺序存储的,所以非常适合随机访问的场合。除了尾部插入和删除元素,往往性能会相对较差,比如我们在中间位置插入一个元素,需要移动后续所有元素。
  • LinkedList进行节点插入、 删除却要高效得多,但是随机访问性能则要比动态数组慢
  • 在应用开发中,如果事先可以估计到,应用操作是偏向于插入、删除,还是随机访问较多,就可以针对性的进行选择

数组和链表的对比

  • 数组
    • 最好用于索引有语意的情况,例如scores[2]
    • 最大的优点:支持快速查询(随机访问)
    • 物理存储单元上连续
  • 链表
    • 不适合用于索引有语意的情况
    • 优点:动态数据结构,不需要处理固定容量的问题
    • 缺点:丧失了随机访问能力
    • 物理存储单元上不连续

ArrayList部分源码分析

add(E e)

    /**
     * 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 static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }

    private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        // 扩容为原来的1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        // 如果扩容1.5倍后还不满足需求,直接扩容为需求值
        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);
    }

Reference

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xylitolz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值