• 【JDK】JDK源码分析-Vector


    概述

    上文「JDK源码分析-ArrayList」主要分析了 ArrayList 的实现原理。本文分析 List 接口的另一个实现类:Vector。

    Vector 的内部实现与 ArrayList 类似,也可以理解为一个「可变数组」。其继承结构如下(省略部分接口):

    PS: 由于 Vector 目前使用较少,且官方也推荐在无线程安全的需求时使用 ArrayList 代替 Vector,这里仅研究其实现原理。

    stackoverflow 也有相关的讨论:

    https://stackoverflow.com/questions/1386275/why-is-java-vector-and-stack-class-considered-obsolete-or-deprecated

    仍然从其构造器入手进行分析。 

    构造器

    Vector 对外提供四个构造器(内部可以认为是两个),其一:

    protected Object[] elementData;
    
    protected int capacityIncrement;
    
    // 无参构造器
    public Vector() {
        this(10);
    }
    
    // 指定容量的构造器
    public Vector(int initialCapacity) {
        this(initialCapacity, 0);
    }
    
    // 指定初始容量和容量增长因子的构造器
    public Vector(int initialCapacity, int capacityIncrement) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
        this.capacityIncrement = capacityIncrement;
    }        

    与 ArrayList 类似,Vector 内部也维护了一个 Object 类型的数组(elementData)来存储元素(默认初始容量也是 10)。不同的是:Vector 比 ArrayList 的构造器多了一个参数 capacityIncrement,该变量也导致了二者的扩容方式略有不同,后面进行分析。

    其二:入参为集合的构造器

    public Vector(Collection<? extends E> c) {
        elementData = c.toArray();
        elementCount = elementData.length;
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
    }

    扩容原理分析

    我们仍从其 add() 方法入手进行分析:

    public synchronized boolean add(E e) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = e;
        return true;
    }   

    注意这里的关键字 synchronized。观察可以发现:Vector 内部许多方法都使用了该关键字,这也是 Vector 实现线程安全的方式,简单粗暴!

    其扩容方法实现如下:

    /**
     * The number of valid components in this {@code Vector} object.
     * Components elementData[0] through
     * elementData[elementCount-1] are the actual items.
     */
    protected int elementCount;
    
    /*
     * 该方法是非同步的
     * 因为 Vector 内部调用该方法的地方都使用了 synchronized 关键字进行同步,这里不再额外使用
     */
    private void ensureCapacityHelper(int minCapacity) {
        // 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 + ((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;
    }                

    从这里可以看出,Vector 与 ArrayList 的扩容方式基本一致,只是新容量的计算方式有所不同,这里分析下其新容量大小:

    int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity);

    Vector 计算扩容后的新容量时,根据 capacityIncrement 的值可以分为两种情况:

    1. capacityIncrement > 0:新容量 = 旧容量 + capacityIncrement;

    2. capacityIncrement <= 0:新容量 = 旧容量 * 2。

    线程安全性

    Vector 是线程安全的,它实现线程安全的方式也很简单粗暴:直接在方法上使用 synchronized 关键字进行同步。

    Vector 小结

    1. 与 ArrayList 类似,Vector 也可以认为是「可变数组」;

    2. 扩容原理与 ArrayList 基本一致,只是新容量计算方式略有不同:指定增长容量时,新容量为旧容量 + 增长容量;否则扩容为旧容量的 2 倍;

    3. 线程安全的,实现方式简单(synchronized);

    4. 当前使用较少,这里仅学习其实现原理。 

    Stay hungry, stay foolish.

    PS: 本文首发于微信公众号。

  • 相关阅读:
    jquery 左右滚动插件
    MagicAjax使用及注意事项~!!!AJAX无刷新的DLL文件!!
    android 中播放声音要注意的细节
    JNIEnv*的常用函数详解
    http协议上传数据的 优化 方法
    jni 设计的哲学
    listview动态加载数据,并更新数据列表
    Android HOME键的屏蔽
    Django在pycharm业余版进行创建项目文件
    SQL Server 日常维护查询当前正在执行的语句、死锁、堵塞
  • 原文地址:https://www.cnblogs.com/jaxer/p/11105444.html
Copyright © 2020-2023  润新知