Vector知道这些差不多够了




1、概述

我以为Vector貌似使用的并不是很多,如果想学习该集合,一定要把ArrayList集合看明白,因为两者相同的太多了。

在学习Vector集合的时候,我们可以简单的理解成加了锁的ArrayList。由于与ArrayList数据结构相同,所以我们接下来的讲解都是与ArrayList做比较。

Vector集合始于JDK1.0,在JDK1.2的时候,该类改进了List接口,使其成为了Java Collections的成员。所以Vector集合中很多之前写的方法都因为实现了List接口中的方法而被抛弃使用,因为后者使用太简单!!!




2、基本组成


2.1、成员方法

1、用来存放数据的集合

protected Object[] elementData;

2、集合元素的个数

protected int elementCount;

3、容量的增量判定数,用于扩容处的判定

protected int capacityIncrement;

2.2、构造方法

1、空参构造方法

public Vector() {
    //默认初始容量为10
    this(10);
}

2、初始化集合的时候,传入指定的容量

public Vector(int initialCapacity) {
    this(initialCapacity, 0);
}

3、初始化集合的时候,传入指定的容量以及容量的增量判定数

public Vector(int initialCapacity, int capacityIncrement) {
    super();
    //初始化集合小于0,就抛出异常
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    //新建一个长度为initialCapacity的数组,再赋值给elementData
    this.elementData = new Object[initialCapacity];
    //获取制定的容量增量的判定数
    this.capacityIncrement = capacityIncrement;
}

2.3、成员方法

由于分析的思路和ArrayList的思路基本相同,所以我这里只分析几个我觉得典型的方法

1、增加数据(使用add方法的时候,会跳转到这个方法)

public synchronized void insertElementAt(E obj, int index) {
    
    //如果传入的数据不符合规范,我们就抛出异常
    if (index > elementCount) {
        throw new ArrayIndexOutOfBoundsException(index
                                                 + " > " + elementCount);
    }
    
    //操作数+1
    modCount++;
    
    //获取到集合的数据个数
    final int s = elementCount;
    
    //拿到现有的集合数据
    Object[] elementData = this.elementData;
    //如果容量不足就扩容
    if (s == elementData.length)
        elementData = grow();
    
    //与ArrayList使用方式相同,进行数组拷贝
    System.arraycopy(elementData, index,
                     elementData, index + 1,
                     s - index);
    
    //将我们的数据放入,拷贝回来的集合中
    elementData[index] = obj;
    
    //集合的个数+1
    elementCount = s + 1;
}

2、删除方法

public synchronized void removeElementAt(int index) {
    
    //校验数据是否合法
    if (index >= elementCount) {
        throw new ArrayIndexOutOfBoundsException(index + " >= " +
                                                 elementCount);
    }
    else if (index < 0) {
        throw new ArrayIndexOutOfBoundsException(index);
    }
    
    //获取要删除的数据的位置
    int j = elementCount - index - 1;
    
    //如果位置大于0,就进行数据的拷贝
    if (j > 0) {
        System.arraycopy(elementData, index + 1, elementData, index, j);
    }
    
    //集合操作数+1,集合的元素-1
    modCount++;
    elementCount--;
    
    //将删除的位置赋值为null,方便垃圾回收
    elementData[elementCount] = null; /* to let gc do its work */
}

3、修改方法

public synchronized E set(int index, E element) {
    
    //判断数据是否合法
    if (index >= elementCount)
        throw new ArrayIndexOutOfBoundsException(index);

    //根据对应的index值,拿到对应的数据值,并复制给oldValue
    E oldValue = elementData(index);
    
    //设置新的数据值
    elementData[index] = element;
    
    //返回oldValue
    return oldValue;
}

4、查找方法

public synchronized E get(int index) {
    //判断数据是否合法
    if (index >= elementCount)
        throw new ArrayIndexOutOfBoundsException(index);

    //直接根据index查找,然后返回
    return elementData(index);
}

我们不难发现,我们的这四个增删改查方法,都添加了synchronized锁,这也就是Vector的特点之一




3、代码编写上

其实在分析Vector的代码时,我们不难发现它与ArrayList代码风格的不一致性。

ArrayList

public E get(int index) {
    Objects.checkIndex(index, size);
    checkForComodification();
    return root.elementData(offset + index);
}

Vector

public synchronized E get(int index) {
    if (index >= elementCount)
        throw new ArrayIndexOutOfBoundsException(index);

    return elementData(index);
}

同样是对于传入index的合法性校验,前者是直接调用其他方法进行,而后者是直接在方法体中进行判定。当然如果让我来写的话,肯定写出来的是后面这一种。但是前者有一个明显的优势就是提高了代码的复用性。对于get方式传入index时的校验方法,在set以及remove方式中都能够使用,继而达到代码复用的效果!!!

当然还有很多方法的




4、总结

特点:

  • 采用动态数组的方式实现,默认的构造方法创建容量为10的集合

  • 完成扩容后,新的集合的容量是旧集合的两倍

    int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                             capacityIncrement : oldCapacity);
    
  • 由于是动态数组的数据结构,所以依然不适合做删除或者插入

  • 为了防止扩容带来的性能损耗和空间上的浪费,建议在初始化集合的时候,给出指定的容量

  • 由于方法使用了synchronized锁,所以是线程安全的,也正是如此,在单线程情况下因为性能的低,所以不建议使用

至此我们关于List接口下的集合就都学习完毕,开心!!!

虽然后面还有很多呀!
Set接口下的:HashSet、TreeSet、LinkHashSet

Map接口下的:HashMap、ConcurrentHashMap、HashTable、TreeMap、LinkHashMap

好吧,一个集合背后的居然要学习十一个类。emmm!!!

发布了45 篇原创文章 · 获赞 17 · 访问量 3686

猜你喜欢

转载自blog.csdn.net/qq_44377709/article/details/105330397