Vector,LinkedList和ArrayList之间的异同

1.相同点

Arraylist,LinkedList和Vector都是List集合的实现类,其相同点也是List集合的特点,换而言之,其特点可以总结为

他们都是有序的,元素可重复的集合.有序指的是元素的存入与输出的顺序一致,也就是先进先出;


2.不同点

(1)Arraylist

ArrayList底层使用的是Java数组来存储集合中的内容,这个数组是Object类型的:

[java]  view plain  copy
  1. transient Object[] elementData;  

这里所定义的elementData只能在包内调用,代表的是其中的元素

定义的size表示数组的长度:

[java]  view plain  copy
  1. private int size;  

Arraylist代码中有个常量,表示数组的默认容量,大小为10:

[java]  view plain  copy
  1. /** 
  2.  * Default initial capacity. 
  3.  */  
  4. private static final 

当我们在给ArrayList 放入元素时,ArrayList 数组的大小会自动对数组进行扩容具体过程如下

[java]  view plain  copy
  1. //添加元素
    1. //添加元素  
    2.  public boolean add(E e) {  
    3.         ensureCapacityInternal(size + 1);  // Increments modCount!!  
    4.         elementData[size++] = e;  
    5.         return true;  
    6.     } 
  2.     }  

在这里我们可以使用一下反射来查看Arraylist的数组长度

[java]   查看纯 文本 
list arrarlistasda s
  1.   static void print (List arraylist) throws Exception {
  2.  //得到类的对象
  3.        Class c = arraylist.getClass();
  4.         //获得属性值
  5.       Filed f = c.getDeclaredField(“elementData”);
  6.    //设置为可以访问的属性
  7. f.setAccessible(true);
  8. Object [] o =(Object [])f.get(arraylist);
  9. System.out.println(o.length);
  10. }

我们调用这个方法就可以得到Arraylist数组的长度

扫描二维码关注公众号,回复: 1444940 查看本文章

我们也可以查看Arraylist的源代码中增加的后续方法

 private void ensureCapacityInternal(int minCapacity) {  
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {  
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);  
        }  
  
        ensureExplicitCapacity(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;  
        int newCapacity = oldCapacity + (oldCapacity >> 1);//扩容长度0.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);//数组扩容  
    }  
  
    private static int hugeCapacity(int minCapacity) {  
        if (minCapacity < 0) // overflow  
            throw new OutOfMemoryError();  
        return (minCapacity > MAX_ARRAY_SIZE) ?  
            Integer.MAX_VALUE :  
            MAX_ARRAY_SIZE;  
    }  

Arraylist每次扩容后,长度都是原来的1.5倍。

 简单来说,ArrayLis是实现了基于动态数组的数据结构,由于使用索引从指定的位置(用index)检索一个对象,他的查询效率很高,由于在非末尾插入和删除时需要重新移动数据,所以他的删除或者插入的效率比较低。每次自增0.5倍容量


(2)Vector

我们可以看看Vector的源代码,这时我们会发现,Vector的构造方法和Arraylist的基本一致,但是Vector与Arraylist存在了一个最大的差异,可以从add()方法看出

[java]  view plain  copy
  1.  //Vector  
  2. public synchronized boolean add(E e) {  
  3.         modCount++;  
  4.         ensureCapacityHelper(elementCount + 1);  
  5.         elementData[elementCount++] = e;  
  6.         return true;  
  7.     }  
  8.   
  9.   
  10. //ArrayList  
  11. public boolean add(E e) {  
  12.         ensureCapacityInternal(size + 1);  // Increments modCount!!  
  13.         elementData[size++] = e;  
  14.         return true;  
  15.     }  

相对于Arraylist,Vector是上了锁的,这使得Vector的线程是安全的,但是这也会导致Vector的效率比Arraylist要低.

我们可以在看一下Vector增加后的方法

[java]  view plain  copy
  1. private void grow(int minCapacity) {  
  2.     // overflow-conscious code  
  3.     int oldCapacity = elementData.length;  
  4.     int newCapacity = oldCapacity + ((capacityIncrement > 0) ?  
  5.                                      capacityIncrement : oldCapacity);  
  6.     if (newCapacity - minCapacity < 0)  
  7.         newCapacity = minCapacity;  
  8.     if (newCapacity - MAX_ARRAY_SIZE > 0)  
  9.         newCapacity = hugeCapacity(minCapacity);  
  10.     elementData = Arrays.copyOf(elementData, newCapacity);  
  11. }  
  12.   
  13. private static int hugeCapacity(int minCapacity) {  
  14.     if (minCapacity < 0// overflow  
  15.         throw new OutOfMemoryError();  
  16.     return (minCapacity > MAX_ARRAY_SIZE) ?  
  17.         Integer.MAX_VALUE :  
  18.         MAX_ARRAY_SIZE;  
  19. }  

可以发现,Vector每次改变容量都是以原容量的1倍进行增长的.

综上所述,Vector可以当成是一个安全的Arraylist来使用,不过效率比Arraylist要低;

(3)LinkedList

LinkedList可以直译为链表,顾名思义LinkedList一定是和链表脱不开关系的

在API中对LinkedList是这样描述的:List 接口的链接列表实现。实现所有可选的列表操作,并且允许所有元素(包括 null)。除了实现 List 接口外,LinkedList 类还为在列表的开头及结尾 getremove 和 insert 元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列双端队列

事实上LinkedList是一个双向的链表,那么他肯定会具备链表的特点 

在插入、删除集合中任何位置的元素所花费的时间都是一样的,但它在索引一个元素的时候比较慢。

[java]  view plain  copy
  1. transient Node<E> first;  
  2.   
  3. transient Node<E> last;  
我们用add和get方法举例简单的了解一下LinkedList的工作原理

[java]  view plain  copy
  1.     public boolean add(E e) {  
  2.         linkLast(e);  
  3.         return true;  
  4.     }  
  5.  void linkLast(E e) {  
  6.         final Node<E> l = last;  
  7.         final Node<E> newNode = new Node<>(l, e, null);  
  8.         last = newNode;  
  9.         if (l == null)  
  10.             first = newNode;  
  11.         else  
  12.             l.next = newNode;  
  13.         size++;  
  14.         modCount++;  
  15.     }  
  16. public E get(int index) {  
  17.         checkElementIndex(index);  
  18.         return node(index).item;  
  19.     }  
LinkedList的工作原理并不是该文重点所以在此不再赘述了。我们需要知道的是由于LinkedList是一个双链表,所以如果我想得到他里面的一个元素我需要一个个的去找,当我需要对这个插入和删除一个元素的时候只需要修改他的节点而不需要对数据进行挪动。

由此我们可以总结出LinkedList的特点:LinkedLis是实现了基于双链表的数据结构,在插入、删除集合中任何位置的元素所花费的时间都是一样的,但它在索引一个元素的时候比较慢。

还有一点,由于LinkedList实现了 Deque 接口,为 addpoll 提供先进先出队列操作,以及其他堆栈和双端队列操作。我们也可以用LinkedList来模拟队列和栈。



猜你喜欢

转载自blog.csdn.net/qq_42244588/article/details/80424351