JDK源码学习之Vector、Stack与LinkedList

一、概述

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() {
	E	obj;
	int	len = 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是非线程安全类,是双向链表,删除速度快,查找慢。




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值