集合源码学习(四):Vector

来源:互联网 发布:知乎客户端 pc 编辑:程序博客网 时间:2024/06/05 13:27

Vector是什么?

Vector是一个集合,和在实现结构上和ArrayList很相似,包括增加,修改,删除等等操作,和ArrayList实现算法均一致。所以本篇博文不再像前一篇文章集合源码学习(三):ArrayList 般介绍具体实现类型方方面面。所以想继续了解Vector源码读者可以先看ArrayList这篇,再来读这篇就可以了。
而与ArrayList的最大不同点,就是Vector里面的方法都考虑了线程安全,在很多操作方法上都加了synchronized关键字
这篇文章主要分享一些不同与ArrayList特点的地方。

定义头

public class Vector<E>    extends AbstractList<E>    implements List<E>, RandomAccess, Cloneable, java.io.Serializable

同样是可随机访问以及可克隆,继承子AbstractList等。

初始值以及扩容

关于扩容,在数值上和ArrayList并不相同,如果程序员没有指定初值Vector的大小,则默认为10,而在扩容方面,Vector则是用一个capacityIncrement来确定的,同时也要和程序员要求扩容大小来比较,具体看代码及注释:

  /**     * 初始值为设置值,增长值为0默认     */    public Vector(int initialCapacity) {        this(initialCapacity, 0);    }    /**     * 初始值为10,默认增长值为0.     */    public Vector() {        this(10);    }

接下来是关于扩容方面:
依次调用ensureCapacity,ensureCapacityHelper,grow等方法,中间除了一些边界判断语句,基本都是层层嵌套,这里主要贴出grow方法代码:

    private void grow(int minCapacity) {        // overflow-conscious code        int oldCapacity = elementData.length;        //由此可见,如果capacityIncrement>0,就会按照cpacityIncrement大小增加,否则就是2个oldCapacity。        int newCapacity = oldCapacity + ((capacityIncrement > 0) ?                                         capacityIncrement : oldCapacity);        //如果min比调整后的大小还大,那就按照minCapacity来。        if (newCapacity - minCapacity < 0)            newCapacity = minCapacity;        if (newCapacity - MAX_ARRAY_SIZE > 0)            newCapacity = hugeCapacity(minCapacity);        elementData = Arrays.copyOf(elementData, newCapacity);    }

Collections里面的线程安全包装方法

Vector里面也有个subList方法来获得子串,但是与ArrayList的实现不同,因为它被设计为线程安全的,所以直接返回了一个线程安全的包装类,这里介绍一下基本原理。
第一步:

public synchronized List<E> subList(int fromIndex, int toIndex) {        return Collections.synchronizedList(super.subList(fromIndex, toIndex),                                            this);    }

接下来进入Collections.synchronized查看:

static <T> List<T> synchronizedList(List<T> list, Object mutex) {        return (list instanceof RandomAccess ?                new SynchronizedRandomAccessList<>(list, mutex) :                new SynchronizedList<>(list, mutex));    }

返回了一个SynchronizedRandomAccessList,那再去看这个类。

static class SynchronizedRandomAccessList<E>        extends SynchronizedList<E>        implements RandomAccess {        ...SynchronizedRandomAccessList(List<E> list, Object mutex) {            super(list, mutex);        }

这个类完全指示对super的一个包装SynchronizedList,已看名字就知道是一个线程安全类:

    ...    final List<E> list;        SynchronizedList(List<E> list) {            super(list);            this.list = list;        }        SynchronizedList(List<E> list, Object mutex) {            super(list, mutex);            this.list = list;        }        public boolean equals(Object o) {            if (this == o)                return true;            synchronized (mutex) {return list.equals(o);}        }        public int hashCode() {            synchronized (mutex) {return list.hashCode();}        }        public E get(int index) {            synchronized (mutex) {return list.get(index);}        }        public E set(int index, E element) {            synchronized (mutex) {return list.set(index, element);}        }        public void add(int index, E element) {            synchronized (mutex) {list.add(index, element);}        }    ...

可以发现里面有众多方法,并且都是Vector中操作名字相同的方法,指示都是对当前Vector加锁,再进行操作的线程安全方法。
而其中方法实现原理,都是基于适配器模式间接使用Vector来进行操作,这是典型java多态的应用,如果通过debug源码,可以很清楚的看清这一点。
以上就是Collections里面synchronizedList包装方法的原理,其他方法可以类比理解。

Vector里面的Spliterator-VectorSpliterator

或许会有一个疑问,Vector不是线程安全的么?为啥也有Spliterator?
对于Spliterator不懂的读者可以看我这篇文章:集合源码学习(二):Spliterator
Spliterator可是一个支持并行的迭代器啊。
不多说,先看看源码:

  static final class VectorSpliterator<E> implements Spliterator<E> {        private final Vector<E> list;        private Object[] array;        private int index; // current index, modified on advance/split        private int fence; // -1 until used; then one past last index        private int expectedModCount; // initialized when fence set        ...    这些和ArrayListSpliterator没有特别之处,就不多说    ...        public boolean tryAdvance(Consumer<? super E> action) {            if (action == null)                throw new NullPointerException();            int hi = getFence(), i = index;            if (i < hi) {                index = i + 1;                @SuppressWarnings("unchecked") E e = (E)list.elementData[i];                action.accept(e);                if (list.modCount != expectedModCount)                    throw new ConcurrentModificationException();                return true;            }            return false;        }        //forEachRemaining方法和tryAdvance原理类似

和ArrayListSpliterator一样,也会有expectedModCount来保证fast-fail机制,防止在通过迭代器遍历的时候,Vector结构突然被改变(add和remove)。而不同的是,VectorSpliterator还传入了一个Object[]数组,java里面数组也是引用类型,也就是把Vector中的elementData传进来了。这样在tryAdvance中,就可以获得Vector中元素了Vector中get方法是同步的),也就可以进行并行的tryAdvance和forEachRemaining操作了。

确实在Vector上收获蛮多喔^^

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 征信账号注册怎么办 注册不了征信号怎么办 阿里巴巴一键铺货到淘宝发货怎么办 淘宝购物的问题怎么办 买家评价被删除怎么办 淘宝订单虚假交易怎么办 被判定虚假物流怎么办 淘宝有虚假交易怎么办 微信辅助不了怎么办 微信验证失败怎么办 淘宝占空间太大怎么办 淘宝占用空间大怎么办 ipad空间不够用怎么办 ipadmini密码忘了怎么办 旧ipad特别卡怎么办 苹果ipad反应慢怎么办 手机垃圾多了怎么办 ipad2内存过低怎么办 苹果平板ipad内存不足怎么办 手机dns配置错误怎么办 蓝牙已停止运行怎么办 ipad看电视闪退怎么办 ipad为什么看电视会闪退怎么办 微淘直播延迟怎么办 手机淘宝进群领金币怎么办 做淘客冲销量停止淘客后怎么办 微信中零钱提现怎么办 淘宝买家不签收怎么办 小龙虾没人下单怎么办 淘宝直播不浮现怎么办 淘宝直播看不了怎么办 理财客户说没钱怎么办 投资不给钱了怎么办 工作中遇到挫折怎么办 手机qq出现异常怎么办 农行卡出现异常怎么办 淘宝长期不发货怎么办 快递一直不发货怎么办 申请退款被拒绝怎么办 淘宝的垃圾短信怎么办 如果淘宝不退款怎么办