JDK源码学习之Vector、Stack与LinkedList

来源:互联网 发布:php fetch array 编辑:程序博客网 时间:2024/05/29 19:40

一、概述

Vector 是JDK1.0提供的集合类,Stack是Vector的子类,LinkedList是JKD1.2提供的,是双向链表。


二、源码分析

                  Vector的实现基本跟ArrayList一样,所以就不重复分析了,简单挑出几个方法进行分析


 扩容方法:

         

 private void ensureCapacityHelper(int minCapacity) {int oldCapacity = elementData.length;if (minCapacity > oldCapacity) {    Object[] oldData = elementData;    int newCapacity = (capacityIncrement > 0) ?(oldCapacity + capacityIncrement) : (oldCapacity * 2);        if (newCapacity < minCapacity) {newCapacity = minCapacity;    }            elementData = Arrays.copyOf(elementData, newCapacity);}    }

从该方法就能分析出来,Vector扩容的特点,Vector扩容取决于capacityIncrement变量的值,个人理解相当于步进长度,默认是0,Vector会进行两倍扩容,或者采取原容量+步进长度来扩容,ArrayList会增大0.5倍在加1(HashMap跟负载因子相关默认是0.75),其他方法基本跟ArrayList相同,不再赘述,但是需要注意的是Vector是线程安全的集合,内部方法基本都有同步锁。


下面再来看一下Stack“”,Stack是Vector的子类,通过一定的封装来达到LIFO后入先出来模拟栈的特性。常用的方法有如下三个:


public E push(E item) {addElement(item);return item;    }

压栈,添加数据到栈里。


public synchronized E pop() {Eobj;intlen = size();obj = peek();removeElementAt(len - 1);return obj;    }

弹栈,弹出最后插入的数据,其中的peek方法直接弹出最后数据,如果没有会抛出异常,所以遍历的时候要加上判断

empty()。另外Stack也是个线程安全类。


再来看一下LinkedList ,它也是List接口的一个实现类,支持clone,序列化,还是实现了Deque接口——双端接口,

所以LinkedList可以实现FIFO,或者实现栈的功能,它提供了丰富的方法让我们可以灵活使用来达到自己想要的效果。

先来看一下它的实现基础——属性


 private transient Entry<E> header = new Entry<E>(null, null, null);//标示头元素

 private transient int size = 0;//存储队列大小

其中Entry是一个静态类,内部属性有E element 存储当前节点的value,Entry<E> next 存储当前节点的下一个Entry的引用,Entry<E> previous 存储当前节点的前一个Entry的引用。所以整个LinkedList的内部数据结构我们就明白了,其实就是一个链表,我们可以通过header来从前向后,或者从后向前进行操作,从而实现双端操作。

默认生成的linkedList不会额外创建空间,header.next = header.previous = header;另外header是不存储数值的,只是作为一个标记节点,真正存储元素开始的位置是是header.next。整个LinkedList可以看做一个“环”。通过数据结构我们就能知道,LinkedList查找效率比较低——从头或者尾一步步找,但是删除效率很高——找到之后直接修改引用即可,不用像ArrayList还要复制数组,另外LinkedList也允许存入null


常用的方法有:

public E getFirst()//得到第一个的元素

public E getLast()//得到最后的元素

 实现了List接口所以很多方法跟ArrayList一样,内部实现稍有不同

主要看一下删除方法

 public E remove(int index) {        return remove(entry(index));    }    /**     * Returns the indexed entry.     */    private Entry<E> entry(int index) {        if (index < 0 || index >= size)            throw new IndexOutOfBoundsException("Index: "+index+                                                ", Size: "+size);        Entry<E> e = header;        if (index < (size >> 1)) {//判断index离头还是尾近            for (int i = 0; i <= index; i++)                e = e.next;        } else {            for (int i = size; i > index; i--)                e = e.previous;        }        return e;    }

private E remove(Entry<E> e) {if (e == header)    throw new NoSuchElementException();        E result = e.element;e.previous.next = e.next;e.next.previous = e.previous;        e.next = e.previous = null;        e.element = null;size--;modCount++;        return result;    }

通过index查找速度比通过对象找快,内部有判断选择合适的方向开始查找,通过分析可以看出LinkedList的删除操作时间复杂度是o(n)(要先遍历查找)。



三、总结

Vector与Stack都是JDK1.0提供的线程安全类,由于同步效率比较低,没有同步需求的情况下不建议使用该集合。

LinkedList是非线程安全类,是双向链表,删除速度快,查找慢。