请你谈谈对ArrayList && Vector && LinkedList源码解读?

1ArrayList解析

1.1 首先,我们来看一下ArrayList的属性:

在这里插入图片描述
ArrayList底层其实就是一个数组,ArrayList中有扩容这么一个概念,正因为它扩容,所以它能够实现“动态”增长。

1.2 我们来看看构造方法来印证我们上面说得对不对:

在这里插入图片描述

1.3 add方法可以说是ArrayList比较重要的方法了,我们来总览一下:

在这里插入图片描述

1 add(E e)
 public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { // 如果是第一次添加元素:默认的内部数组为DEFAULTCAPACITY_EMPTY_ELEMENTDATA, 我们就初始化容量为:DEFAULT_CAPACITY = 10。
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); //想要得到最小的容量(不浪费资源)
        }
        ensureExplicitCapacity(minCapacity);
    }

随后调用ensureExplicitCapacity()来确定明确的容量,我们也来看看这个方法是怎么实现的:
在这里插入图片描述
所以,接下来看看grow()是怎么实现的:
在这里插入图片描述
add(E e)的基本实现:
1 检查数组容量是是否足够(通过 size + 1 与 内部数组的大小 作比较):
足够的话,直接添加;
不够的话,扩容为原来的1.5倍;

2 add(int index, E element)
检查下标是否越界
空间检查,如果有需要进行扩容
插入元素

在这里插入图片描述
我们发现,与扩容相关ArrayList的add方法底层其实都是arraycopy()来实现的,看到arraycopy(),我们可以发现:该方法是由C/C++来编写的,并不是由Java实现:
在这里插入图片描述

3 get()方法

在这里插入图片描述
在这里插入图片描述

4set()方法

在这里插入图片描述

5remove()方法
检查下标
删除元素
计算出需要移动的个数,并移动
设置为null,让Gc回收

在这里插入图片描述
总结:

1 ArrayList是基于动态数组实现的,在增删时候,需要数组的拷贝复制。
2 ArrayList的默认初始化容量是10,每次扩容时候增加原先容量的一半,也就是变为原来的1.5倍。
3 删除元素时不会减少容量,若希望减少容量则调用trimToSize()4 它不是线程安全的。
5 它能存放null值。

2 Vector

Vector是jdk1.2的类了,比较老旧的一个集合类:
在这里插入图片描述
Vector底层也是数组,与ArrayList最大的区别就是:同步(线程安全) synchronized修饰的同步方法:在这里插入图片描述
如果想要ArrayList实现同步,可以使用Collections的方法:List list = Collections.synchronizedList(new ArrayList(...));,就可以实现同步了。

ArrayList在底层数组不够用时在原来的基础上扩展0.5倍,Vector是扩展1倍:在这里插入图片描述

3LinkedList

LinkedList底层是双向链表,LinkedList实现了Deque接口,因此,我们可以操作LinkedList像操作队列和栈一样。

1构造方法
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;
        }
    }

在这里插入图片描述

2add方法

add方法实际上就是往链表最后添加元素:

public boolean add(E e) {
        linkLast(e);
        return true;
    }
 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++;
    }

3remove方法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4get方法
 public E get(int index) {
        checkElementIndex(index);
        return node(index).item;
    }

在这里插入图片描述

5set方法
public E set(int index, E element) {
        checkElementIndex(index);
        Node<E> x = node(index);
        E oldVal = x.item;
        x.item = element;
        return oldVal;
    }

4总结

ArrayList:
1 底层实现是数组
2 ArrayList的默认初始化容量是10,每次扩容时候增加原先容量的一半,也就是变为原来的1.5倍
3 在增删时候,需要数组的拷贝复制(navite 方法由C/C++实现)

LinkedList:
底层实现是双向链表[双向链表方便实现往前遍历]

Vector:
底层是数组,现在已少用,被ArrayList替代,原因有两个:
Vector所有方法都是同步,有性能损失。
Vector初始length是10 超过length时 以100%比率增长,相比于ArrayList更多消耗内存。

总的来说:查询多用ArrayList,增删多用LinkedList。
ArrayList增删慢不是绝对的(在数量大的情况下,已测试):

如果增加元素一直是使用add()(增加到末尾)的话,那是ArrayList要快

一直删除末尾的元素也是ArrayList要快【不用复制移动位置】

至于如果删除的是中间的位置的话,还是ArrayList要快。

但一般来说:增删多还是用LinkedList,因为上面的情况是极端的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值