Java集合类源码解析:Vector Java集合类源码解析:Vector

[学习笔记][转载]

Java集合类源码解析:Vector

 

引言

之前的文章我们学习了一个集合类 ArrayList,今天讲它的一个兄弟 Vector
为什么说是它兄弟呢?因为从容器的构造来说,Vector 简直就是 ArrayList 的翻版,也是基于数组的数据结构,不同的是,Vector的每个方法都加了 synchronized 修饰符,是线程安全的。

类声明

用idea打开 Vector 的源码,不难发现,它的类声明跟 ArrayList 一模一样,都是继承了AbstractList,并且都实现了RandomAccess接口,遍历元素用for循环的效率要优于迭代器。

 * @author  Lee Boynton
 * @author  Jonathan Payne
 * @see Collection
 * @see LinkedList
 * @since JDK1.0 */ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable

值得说明的是,从注释上来看,Vector 是 JDK1.0版本就引进的,属于最古老的集合类的那一批,而ArrayList是 1.2才引进的,所以说,Vector才是哥哥,ArrayList是小弟,哈哈~~~~

基本变量和构造函数

基本变量

Vector 的基本变量有四个,分别是:

  • 底层数组
protected Object[] elementData;
  • 数组元素个数
protected int elementCount;
  • 增长的容量大小,如果这个值小于或等于0,扩容时会扩大 2 倍,
capacityIncrement
  • 最大容量
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

构造函数

//创建初识容量为10的数组,增长量0
public Vector() { this(10); } //创建初识容量可变的数组,增长量为0 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; } //创建一个包含指定集合的数组 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); }

看的出来,Vector的构造器和成员变量和ArrayList大同小异。

成员方法

扩容

Vector 与 ArrayList 虽然很类似,但在扩容大小这方面还是有区别的,ArrayList 默认扩容后的大小为原容量 的1.5倍,而Vector则是先判断增长量大小,如果是非正数,那就扩大为原来的2倍,看一下它的扩容方法:

//参数是最小需要的容量
private void grow(int minCapacity) {
    // overflow-conscious code int oldCapacity = elementData.length; //如果增长量不大于0,扩容为2倍大小 //一般默认创建的容器都是不传增长量的,所以默认增长量是0,也就是默认直接扩容两倍 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的添加方法都是加上 synchronized关键字的,并且添加前检测容量,判断是否扩容:

//加入元素到数组结尾,同步的
public synchronized boolean add(E e) { modCount++; //检测容量 ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = e; return true; } //检测容量大小,超过数组长度就做扩容 private void ensureCapacityHelper(int minCapacity) { // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); } public void add(int index, E element) { insertElementAt(element, index); } //插入对应索引的元素 public synchronized void insertElementAt(E obj, int index) { modCount++; if (index > elementCount) { throw new ArrayIndexOutOfBoundsException(index + " > " + elementCount); } ensureCapacityHelper(elementCount + 1); //插入元素前,把其索引后面的元素统一后移一位 System.arraycopy(elementData, index, elementData, index + 1, elementCount - index); elementData[index] = obj; elementCount++; } public synchronized void addElement(E obj) { modCount++; //保证容量足够 ensureCapacityHelper(elementCount + 1); //直接设置最后一个元素的数据 elementData[elementCount++] = obj; } //添加整个集合 public synchronized boolean addAll(Collection<? extends E> c) { modCount++; //把集合转为数组对象 Object[] a = c.toArray(); int numNew = a.length; ensureCapacityHelper(elementCount + numNew); //直接复制集合元素到数组后面 System.arraycopy(a, 0, elementData, elementCount, numNew); elementCount += numNew; return numNew != 0; } //在对应的索引处插入一个集合 public synchronized boolean addAll(int index, Collection<? extends E> c) { modCount++; if (index < 0 || index > elementCount) throw new ArrayIndexOutOfBoundsException(index); Object[] a = c.toArray(); int numNew = a.length; ensureCapacityHelper(elementCount + numNew); //计算要移动多少个元素 int numMoved = elementCount - index; if (numMoved > 0) //把插入位置后面的元素后移这么多位 System.arraycopy(elementData, index, elementData, index + numNew, numMoved); //复制元素数组 System.arraycopy(a, 0, elementData, index, numNew); elementCount += numNew; return numNew != 0; }

Vector的添加方法代码不是很复杂,跟ArrayList 一样,本质上都是对数组做插入数据的操作,不同的是,方法都加了synchronized 修饰,所以,它的添加方法都是线程安全的。

其他操作元素的方法也是这样的套路,这里不打算一一列举了,因为都跟ArrayList 差不多,另外,Vector 比 ArrayList 多了一个迭代方法

public Enumeration<E> elements() {
    return new Enumeration<E>() { int count = 0; public boolean hasMoreElements() { return count < elementCount; } public E nextElement() { synchronized (Vector.this) { if (count < elementCount) { return elementData(count++); } } throw new NoSuchElementException("Vector Enumeration"); } }; }

返回的是一个Enumeration 接口对象,大概也是个容器接口,没用过,不说太多。

Vector 对比 ArrayList

最后,总结一下 Vector 和 ArrayList 的对比吧。

相同点:

  • 底层都是基于数组的结构,默认容量都是10;

  • 都实现了RandomAccess 接口,支持随机访问;

  • 都有扩容机制;

区别:

  • Vector 的方法有做同步操作,是属于线程安全的,而ArrayList 是非线程安全的;

  • Vector默认情况下扩容后的大小为原来的2倍,而ArrayList 是1.5倍;

  • Vector 比 ArrayList 多了一种迭代器 Enumeration;

虽然Vector相较ArrayList做了同步的处理,但这样也影响了效率,因为每次调用方法都要获取锁,所以,一般情况下,对集合的线程安全没有需求的话,推荐使用 ArrayList。


版权声明:本文为转载文章,原文地址https://www.cnblogs.com/yeya/p/9970654.html

引言

之前的文章我们学习了一个集合类 ArrayList,今天讲它的一个兄弟 Vector
为什么说是它兄弟呢?因为从容器的构造来说,Vector 简直就是 ArrayList 的翻版,也是基于数组的数据结构,不同的是,Vector的每个方法都加了 synchronized 修饰符,是线程安全的。

类声明

用idea打开 Vector 的源码,不难发现,它的类声明跟 ArrayList 一模一样,都是继承了AbstractList,并且都实现了RandomAccess接口,遍历元素用for循环的效率要优于迭代器。

 * @author  Lee Boynton
 * @author  Jonathan Payne
 * @see Collection
 * @see LinkedList
 * @since JDK1.0 */ public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable

值得说明的是,从注释上来看,Vector 是 JDK1.0版本就引进的,属于最古老的集合类的那一批,而ArrayList是 1.2才引进的,所以说,Vector才是哥哥,ArrayList是小弟,哈哈~~~~

基本变量和构造函数

基本变量

Vector 的基本变量有四个,分别是:

  • 底层数组
protected Object[] elementData;
  • 数组元素个数
protected int elementCount;
  • 增长的容量大小,如果这个值小于或等于0,扩容时会扩大 2 倍,
capacityIncrement
  • 最大容量
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

构造函数

//创建初识容量为10的数组,增长量0
public Vector() { this(10); } //创建初识容量可变的数组,增长量为0 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; } //创建一个包含指定集合的数组 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); }

看的出来,Vector的构造器和成员变量和ArrayList大同小异。

成员方法

扩容

Vector 与 ArrayList 虽然很类似,但在扩容大小这方面还是有区别的,ArrayList 默认扩容后的大小为原容量 的1.5倍,而Vector则是先判断增长量大小,如果是非正数,那就扩大为原来的2倍,看一下它的扩容方法:

//参数是最小需要的容量
private void grow(int minCapacity) {
    // overflow-conscious code int oldCapacity = elementData.length; //如果增长量不大于0,扩容为2倍大小 //一般默认创建的容器都是不传增长量的,所以默认增长量是0,也就是默认直接扩容两倍 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的添加方法都是加上 synchronized关键字的,并且添加前检测容量,判断是否扩容:

//加入元素到数组结尾,同步的
public synchronized boolean add(E e) { modCount++; //检测容量 ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = e; return true; } //检测容量大小,超过数组长度就做扩容 private void ensureCapacityHelper(int minCapacity) { // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); } public void add(int index, E element) { insertElementAt(element, index); } //插入对应索引的元素 public synchronized void insertElementAt(E obj, int index) { modCount++; if (index > elementCount) { throw new ArrayIndexOutOfBoundsException(index + " > " + elementCount); } ensureCapacityHelper(elementCount + 1); //插入元素前,把其索引后面的元素统一后移一位 System.arraycopy(elementData, index, elementData, index + 1, elementCount - index); elementData[index] = obj; elementCount++; } public synchronized void addElement(E obj) { modCount++; //保证容量足够 ensureCapacityHelper(elementCount + 1); //直接设置最后一个元素的数据 elementData[elementCount++] = obj; } //添加整个集合 public synchronized boolean addAll(Collection<? extends E> c) { modCount++; //把集合转为数组对象 Object[] a = c.toArray(); int numNew = a.length; ensureCapacityHelper(elementCount + numNew); //直接复制集合元素到数组后面 System.arraycopy(a, 0, elementData, elementCount, numNew); elementCount += numNew; return numNew != 0; } //在对应的索引处插入一个集合 public synchronized boolean addAll(int index, Collection<? extends E> c) { modCount++; if (index < 0 || index > elementCount) throw new ArrayIndexOutOfBoundsException(index); Object[] a = c.toArray(); int numNew = a.length; ensureCapacityHelper(elementCount + numNew); //计算要移动多少个元素 int numMoved = elementCount - index; if (numMoved > 0) //把插入位置后面的元素后移这么多位 System.arraycopy(elementData, index, elementData, index + numNew, numMoved); //复制元素数组 System.arraycopy(a, 0, elementData, index, numNew); elementCount += numNew; return numNew != 0; }

Vector的添加方法代码不是很复杂,跟ArrayList 一样,本质上都是对数组做插入数据的操作,不同的是,方法都加了synchronized 修饰,所以,它的添加方法都是线程安全的。

其他操作元素的方法也是这样的套路,这里不打算一一列举了,因为都跟ArrayList 差不多,另外,Vector 比 ArrayList 多了一个迭代方法

public Enumeration<E> elements() {
    return new Enumeration<E>() { int count = 0; public boolean hasMoreElements() { return count < elementCount; } public E nextElement() { synchronized (Vector.this) { if (count < elementCount) { return elementData(count++); } } throw new NoSuchElementException("Vector Enumeration"); } }; }

返回的是一个Enumeration 接口对象,大概也是个容器接口,没用过,不说太多。

Vector 对比 ArrayList

最后,总结一下 Vector 和 ArrayList 的对比吧。

相同点:

  • 底层都是基于数组的结构,默认容量都是10;

  • 都实现了RandomAccess 接口,支持随机访问;

  • 都有扩容机制;

区别:

  • Vector 的方法有做同步操作,是属于线程安全的,而ArrayList 是非线程安全的;

  • Vector默认情况下扩容后的大小为原来的2倍,而ArrayList 是1.5倍;

  • Vector 比 ArrayList 多了一种迭代器 Enumeration;

虽然Vector相较ArrayList做了同步的处理,但这样也影响了效率,因为每次调用方法都要获取锁,所以,一般情况下,对集合的线程安全没有需求的话,推荐使用 ArrayList。

猜你喜欢

转载自www.cnblogs.com/haima1949/p/10757315.html