Vector、ArrayList、LinkedList 有什么区别?

这个问题主要是考察集合框架的问题,主要考察三者之间的设计区别,以及使用时如何选择。然后继续可能考察排序算法的问题。
主要区别:

  • Vector是java早期提供的线程安全的动态数组;ArrayList也是动态数组,但不是线程安全的;而LinkedList与前者不同,LinkedList是使用双向链表存储的,也不是线程安全的。
  • Vector因为是线程安全的,所以在使用时性能比ArrayList要差。
  • Vector和ArrayList可以根据需要自动增加容量,Vector在扩容时是增加1倍,ArrayList在扩容时是增加50%
  • LinkedList是使用双向链表,每个数据结点中都有两个指针,分别指向直接前驱和直接后继。所以插入或删除时速度很快,但随机访问时速度比ArrayList慢。
  • Vector和ArrayList内部元素是以数组形式存储的,所以适合随机访问。除了在头部和尾部插入或删除元素速度会快一点,其他位置性能会相对较差。比如在中间插入一个元素,需要移动后面所有元素。

通过下面一张图,再看一下三者的关系。
这里写图片描述
这里写图片描述
在java集合框架中,Collection接口是所有集合的根,Collection继承Iterable。
然后扩展开提供三大类集合,List、Set、Queue.

  • List是有序的集合,也是Vector、ArrayList、LinkedList实现的接口。允许有相同的元素
  • Set不允许有重复的元素,这是和List最明显的区别
  • Queue是java标准队列的实现,除了集合的基本功能,还支持类似先入先出或者后入先出的特定行为。

再回到Vector、ArrayList、LinkedList,来看下代码实现。
Vector现在很少使用,更多的使用ArrayList。

public class Vector<E> extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable {}
public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable { }
public class LinkedList<E> extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable {}

在实现和继承方面Vector和ArrayList一致,LinkedList不同。
通过代码看一下,在动态扩容方面的区别:

private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        //扩容时增加1倍
        int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                         capacityIncrement : oldCapacity);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }
private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        //扩容时增加50%
        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);
    }

    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

由于LinkedList是双向链表,不存在容量限制,所以不需要扩容,代码如下:

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++;
 }

由于Vector、ArrayList是动态数组,所以如何转化为数组呢?List提供了两个方法:

//返回一个包含 List 中所有元素的数组;
Object[] toArray();
//作用同上,不同的是当参数 a的长度比 List 的元素大时,会使用参数a保存List中的元素;否则会创建一个新的 数组存放 List 中的所有元素;
<T> T[] toArray(T[] a);

ArrayList实现如下:

public Object[] toArray() {
   return Arrays.copyOf(elementData, size);
}

public <T> T[] toArray(T[] a) {
    if (a.length < size)
        // Make a new array of a's runtime type, but my contents:
        return (T[]) Arrays.copyOf(elementData, size, a.getClass());
    System.arraycopy(elementData, 0, a, 0, size);
    if (a.length > size)
        a[size] = null;
    return a;
}

LinkedList转为数组的实现如下:

public Object[] toArray() {
    Object[] result = new Object[size];
    int i = 0;
    //一个一个赋值,没有ArrayList使用copy快
    for (Node<E> x = first; x != null; x = x.next)
        result[i++] = x.item;
    return result;
}
public <T> T[] toArray(T[] a) {
      if (a.length < size)
          a = (T[])java.lang.reflect.Array.newInstance(
                              a.getClass().getComponentType(), size);
      int i = 0;
      Object[] result = a;
      for (Node<E> x = first; x != null; x = x.next)
          result[i++] = x.item;

      if (a.length > size)
          a[size] = null;

      return a;
  }
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值