java 集合类源码分析--Vector

首先我们来看JDK源码中Java.util.Vector的代码,剔除所有的方法和静态变量,

Java.lang.Vector的核心代码如下:

  1. public class Vector<E>
  2. extends AbstractList<E>
  3. implements List<E>, RandomAccess, Cloneable, java.io.Serializable
  4. {
  5. protected Object[] elementData;
  6. /**
  7. * The number of valid components in this {@code Vector} object.
  8. * Components {@code elementData[0]} through
  9. * {@code elementData[elementCount-1]} are the actual items.
  10. *
  11. * @serial
  12. */
  13. protected int elementCount;
  14. protected int capacityIncrement; //可以设定固定增量
  15. }

通过上面的代码我们能看到他是数组存储。

它的构造方法有四个:

  1. /**
  2. * Constructs an empty vector with the specified initial capacity and
  3. * capacity increment.
  4. *
  5. * @param   initialCapacity     the initial capacity of the vector
  6. * @param   capacityIncrement   the amount by which the capacity is
  7. *                              increased when the vector overflows
  8. * @throws IllegalArgumentException if the specified initial capacity
  9. *         is negative
  10. */
  11. public Vector(int initialCapacity, int capacityIncrement) {   //设置初始容量,及固定增量
  12. super();
  13. if (initialCapacity < 0)
  14. throw new IllegalArgumentException("Illegal Capacity: "+
  15. initialCapacity);
  16. this.elementData = new Object[initialCapacity];
  17. this.capacityIncrement = capacityIncrement;
  18. }
  19. /**
  20. * Constructs an empty vector with the specified initial capacity and
  21. * with its capacity increment equal to zero.
  22. *
  23. * @param   initialCapacity   the initial capacity of the vector
  24. * @throws IllegalArgumentException if the specified initial capacity
  25. *         is negative
  26. */
  27. public Vector(int initialCapacity) {    //设置初始容量,不设定固定增量(如果不设定固定增量,则成倍增长)
  28. this(initialCapacity, 0);
  29. }
  30. /**
  31. * Constructs an empty vector so that its internal data array
  32. * has size {@code 10} and its standard capacity increment is
  33. * zero.
  34. */
  35. public Vector() {    //不设置初始容量,初始容量为10,不设定固定增量(如果不设定固定增量,则成倍增长)
  36. this(10);
  37. }
  38. /**
  39. * Constructs a vector containing the elements of the specified
  40. * collection, in the order they are returned by the collection‘s
  41. * iterator.
  42. *
  43. * @param c the collection whose elements are to be placed into this
  44. *       vector
  45. * @throws NullPointerException if the specified collection is null
  46. * @since   1.2
  47. */
  48. public Vector(Collection<? extends E> c) {  //以集合初始化
  49. elementData = c.toArray();
  50. elementCount = elementData.length;
  51. // c.toArray might (incorrectly) not return Object[] (see 6260652)
  52. if (elementData.getClass() != Object[].class)
  53. elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
  54. }

下面我们再看一下 Vector类的 add(E e)方法的源代码:

[java] view plaincopy

  1. /**
  2. * Appends the specified element to the end of this Vector.
  3. *
  4. * @param e element to be appended to this Vector
  5. * @return {@code true} (as specified by {@link Collection#add})
  6. * @since 1.2
  7. */
  8. public synchronized boolean add(E e) {    //从这里的synchronized我们可以知道他是线程同步的
  9. modCount++;
  10. ensureCapacityHelper(elementCount + 1);   //是否需要扩容
  11. elementData[elementCount++] = e;   //后放的永远在最后一位
  12. return true;   // 好像他永远返回true 哦
  13. }

[java] view plaincopy

  1. /**
  2. * This implements the unsynchronized semantics of ensureCapacity.
  3. * Synchronized methods in this class can internally call this
  4. * method for ensuring capacity without incurring the cost of an
  5. * extra synchronization.
  6. *
  7. * @see #ensureCapacity(int)
  8. */
  9. private void ensureCapacityHelper(int minCapacity) {
  10. int oldCapacity = elementData.length;
  11. if (minCapacity > oldCapacity) {    //最新的值如果超出现有容量 扩容
  12. Object[] oldData = elementData;
  13. int newCapacity = (capacityIncrement > 0) ?
  14. (oldCapacity + capacityIncrement) : (oldCapacity * 2);  //如果固定增量不为0则增长固定增量,否则成倍增长
  15. if (newCapacity < minCapacity) {   //新容量还小,这个可能性应该不大
  16. newCapacity = minCapacity;
  17. }
  18. elementData = Arrays.copyOf(elementData, newCapacity);   // 改变数组的大小,这个方法可以记一下
  19. }
  20. }

下面我们再看一下 Vector类的 remove(Object o)方法的源代码:

[java] view plaincopy

  1. /**
  2. * Removes the first occurrence of the specified element in this Vector
  3. * If the Vector does not contain the element, it is unchanged.  More
  4. * formally, removes the element with the lowest index i such that
  5. * {@code (o==null ? get(i)==null : o.equals(get(i)))} (if such
  6. * an element exists).
  7. *
  8. * @param o element to be removed from this Vector, if present
  9. * @return true if the Vector contained the specified element
  10. * @since 1.2
  11. */
  12. public boolean remove(Object o) {
  13. return removeElement(o);      //他是调用的removeElement
  14. }
  15. /**
  16. * Removes the first (lowest-indexed) occurrence of the argument
  17. * from this vector. If the object is found in this vector, each
  18. * component in the vector with an index greater or equal to the
  19. * object‘s index is shifted downward to have an index one smaller
  20. * than the value it had previously.
  21. *
  22. * <p>This method is identical in functionality to the
  23. * {@link #remove(Object)} method (which is part of the
  24. * {@link List} interface).
  25. *
  26. * @param   obj   the component to be removed
  27. * @return  {@code true} if the argument was a component of this
  28. *          vector; {@code false} otherwise.
  29. */
  30. public synchronized boolean removeElement(Object obj) {
  31. modCount++;
  32. int i = indexOf(obj);         //查找obj第一次出现的位置,(Vector是允许重复值的)
  33. if (i >= 0) {
  34. removeElementAt(i);
  35. return true;
  36. }
  37. return false;
  38. }
  39. /**
  40. * Deletes the component at the specified index. Each component in
  41. * this vector with an index greater or equal to the specified
  42. * {@code index} is shifted downward to have an index one
  43. * smaller than the value it had previously. The size of this vector
  44. * is decreased by {@code 1}.
  45. *
  46. * <p>The index must be a value greater than or equal to {@code 0}
  47. * and less than the current size of the vector.
  48. *
  49. * <p>This method is identical in functionality to the {@link #remove(int)}
  50. * method (which is part of the {@link List} interface).  Note that the
  51. * {@code remove} method returns the old value that was stored at the
  52. * specified position.
  53. *
  54. * @param      index   the index of the object to remove
  55. * @throws ArrayIndexOutOfBoundsException if the index is out of range
  56. *          ({@code index < 0 || index >= size()})
  57. */
  58. public synchronized void removeElementAt(int index) {
  59. modCount++;
  60. if (index >= elementCount) {
  61. throw new ArrayIndexOutOfBoundsException(index + " >= " +
  62. elementCount);
  63. }
  64. else if (index < 0) {
  65. throw new ArrayIndexOutOfBoundsException(index);
  66. }
  67. int j = elementCount - index - 1;  // 数组中index以后的元素个数
  68. if (j > 0) {
  69. System.arraycopy(elementData, index + 1, elementData, index, j);   // 数组中index以后的元素,整体前移,(这个方法挺有用的!!)
  70. }
  71. elementCount--;
  72. elementData[elementCount] = null; /* to let gc do its work */
  73. }

从上面的代码我们可以看出 Vector每次只删除最靠前的那个相符的变量。

下面我们再看一下 Vector类的 equals(Object o)方法的源代码:

[java] view plaincopy

  1. /**
  2. * Compares the specified Object with this Vector for equality.  Returns
  3. * true if and only if the specified Object is also a List, both Lists
  4. * have the same size, and all corresponding pairs of elements in the two
  5. * Lists are <em>equal</em>.  (Two elements {@code e1} and
  6. * {@code e2} are <em>equal</em> if {@code (e1==null ? e2==null :
  7. * e1.equals(e2))}.)  In other words, two Lists are defined to be
  8. * equal if they contain the same elements in the same order.
  9. *
  10. * @param o the Object to be compared for equality with this Vector
  11. * @return true if the specified Object is equal to this Vector
  12. */
  13. public synchronized boolean equals(Object o) {
  14. return super.equals(o);   //他是调用的父类AbstractList的equals
  15. }
  16. /**
  17. * Compares the specified object with this list for equality.  Returns
  18. * {@code true} if and only if the specified object is also a list, both
  19. * lists have the same size, and all corresponding pairs of elements in
  20. * the two lists are <i>equal</i>.  (Two elements {@code e1} and
  21. * {@code e2} are <i>equal</i> if {@code (e1==null ? e2==null :
  22. * e1.equals(e2))}.)  In other words, two lists are defined to be
  23. * equal if they contain the same elements in the same order.<p>
  24. *
  25. * This implementation first checks if the specified object is this
  26. * list. If so, it returns {@code true}; if not, it checks if the
  27. * specified object is a list. If not, it returns {@code false}; if so,
  28. * it iterates over both lists, comparing corresponding pairs of elements.
  29. * If any comparison returns {@code false}, this method returns
  30. * {@code false}.  If either iterator runs out of elements before the
  31. * other it returns {@code false} (as the lists are of unequal length);
  32. * otherwise it returns {@code true} when the iterations complete.
  33. *
  34. * @param o the object to be compared for equality with this list
  35. * @return {@code true} if the specified object is equal to this list
  36. */
  37. public boolean equals(Object o) {
  38. if (o == this)
  39. return true;
  40. if (!(o instanceof List))
  41. return false;
  42. ListIterator<E> e1 = listIterator();
  43. ListIterator e2 = ((List) o).listIterator();
  44. while(e1.hasNext() && e2.hasNext()) {
  45. E o1 = e1.next();
  46. Object o2 = e2.next();
  47. if (!(o1==null ? o2==null : o1.equals(o2)))   //判断了三次
  48. //这个方法挺不错的,应该比if(!(null==o1&&null==o2)||(null!=o1&&o1.equals(o2)))(大于等于三次判断)
  49. return false;
  50. }
  51. return !(e1.hasNext() || e2.hasNext());  //长度是否一致
  52. }

下面我们再看一下 Vector类的 hashCode()方法的源代码:

[java] view plaincopy

  1. /**
  2. * Returns the hash code value for this Vector.
  3. */
  4. public synchronized int hashCode() {
  5. return super.hashCode();   //他也是调用的父类AbstractList的hashCode
  6. }
  7. /**
  8. * Returns the hash code value for this list.
  9. *
  10. * <p>This implementation uses exactly the code that is used to define the
  11. * list hash function in the documentation for the {@link List#hashCode}
  12. * method.
  13. *
  14. * @return the hash code value for this list
  15. */
  16. public int hashCode() {
  17. int hashCode = 1;
  18. Iterator<E> i = iterator();
  19. while (i.hasNext()) {
  20. E obj = i.next();
  21. hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
  22. // 在这里用obj,比用i.next()效率高一倍(一直没明白他这为什么用31)
  23. }
  24. return hashCode;
  25. }
0

Vector的底层也是使用数组实现的,而且继承了AbstractList,实现了List接口,看着Vector和ArrayList很像:底层都是用数组实现,都继承了AbstractList,实现了List接口。所以搜了下看看Vector和ArrayList有什么区别。

在The Java Programming Language (Addison-Wesley, June 2000) 中Ken Arnold, James Gosling, 和 David Holmes 是这样描述Vector的,它是更ArrayList类似的一个东西,所以从API的观点来看,它们俩是很相似的。但是,它们之间还是有些微的差别的。

1. 同步性

Vectors是可同步化的,意思就是说,任何操作Vector的内容的方法都是线程安全的,相反的,另一方面,ArrayList是不可同步化的,所以也不是线程安全的。如果你知道了这些的话,你就会发现,Vector的同步会让它在性能发方面有一些小问题。所以,如果你不需要线程安全的话,那么就使用ArrayList吧。为什么要为没有必要的同步付出代价呢?

2. 数据增长

 

实际上,不管是ArrayList还是Vector,在它们内部都是使用一个数组来保存数据的。开发过程中,在使用它们任何一个的时候,你都需要记住这一点。你在往一个ArrayList或者Vector里插入一个元素的时候,如果内部数组空间不够了,ArrayList或者Vector就要扩展它的大小。Vector在默认情况下是增长一倍的大小,而ArrayList增加50%的大小。只要你合理的使用这些类,你就可以结束你在增加新的元素的时候所付出的性能代价。设置初始化容量为你编程过程中所能用到的最大的容量总是最好的办法。精确的指定容量,你可以避免以后改变内部Array容量,所要付出的代价。如果你并不知道到底有多少个数据,当是你知道数据的增长率,Vector确实有一点点优势,因为你可以指定增加值(作者说的方法应该是setSize(int newSize) Sets the size of this vector.)。

3. 查询,插入,删除对象的效率

ArrayList和Vector在从指定位置取得元素,从容器的末尾增加和删除元素都非常的有效,所有的这些操作都能在一个常数级的时间O(1)内完成。但是从一个其他的位置增加和删除一个元素就显得颇为费时,差不多需要的时间为O(n-i),这里的n代表元素个数,i代表要增加和删除的元素所在的位置。这些操作需花费更多的时间,因为你需要挨个移动i和更高位置的元素。那么,以上这些到底说明了什么呢?

  

  这意味着,如果你取得一个元素,或者从数组末尾增加或删除一个元素的话,随便你使用Vector和ArrayList。如果你想要对数组内容做其他操作的话,那么就为自己好另一个容器吧。比如说,LinkedList可以在常数级时间(O1)内为任意一个位置的元素增加和删除。

(这个涉及到ArrayList和LinkedList的实现不同,一个是数组,一个是链表了,这个以后再写一篇博客说说。)

最后,Practical Java (Addison-Wesley, Feb. 2000) Peter Haggar 里的“实践41“建议你使用一个普通的原始的数组来代替Vector和ArrayListe,特别是对效率优先的代码来说。通过使用数组(array),你可以避免同步,额外的方法调用,非理想化的大小改变。你付出的只是额外的开发时间。

看来常用的还是ArrayList,只有在线程安全时才会去使用Vector

时间: 2024-10-12 08:36:31

java 集合类源码分析--Vector的相关文章

java 集合类源码分析--linkedlist

一.源码解析 1. LinkedList类定义2.LinkedList数据结构原理3.私有属性4.构造方法5.元素添加add()及原理6.删除数据remove()7.数据获取get()8.数据复制clone()与toArray()9.遍历数据:Iterator()二.ListItr 一.源码解析 1. LinkedList类定义. public class LinkedList<E> extends AbstractSequentialList<E> implements List

java 集合类源码分析--arrays

本文介绍一下java集合相关类arryas类的内容 .Arrays.sort()数组排序 Java Arrays中提供了对所有类型的排序.其中主要分为Primitive(8种基本类型)和Object两大类. 基本类型:采用调优的快速排序: 对象类型:采用改进的归并排序. 1.对于基本类型源码分析如下(以int[]为例): public static void sort(int[] a, int fromIndex, int toIndex) { //进行数组的界限检查 rangeCheck(a.

java 集合类源码分析--arrayList

ArrayList就是传说中的动态数组,就是Array的复杂版本,它提供了如下一些好处:动态的增加和减少元素.灵活的设置数组的大小...... 认真阅读本文,我相信一定会对你有帮助.比如为什么ArrayList里面提供了一个受保护的removeRange方法?提供了其他没有被调用过的私有方法? 首先看到对ArrayList的定义: public class ArrayList<E> extends AbstractList<E> implements List<E>,

java集合类源码分析-concurrentHashMap

Java Core系列之ConcurrentHashMap实现(JDK 1.7) ConcurrentHashMap类似Hashtable,是HashMap更高效的线程安全版本的实现.不同于Hashtable简单的将所有方法标记为synchronized,它将内部数组分成多个Segment,每个Segment类似一个Hashtable,从而减少锁的粒度,并且它内部有一些比较tricky实现,让get操作很多时候甚至不需要锁(本文代码基于JDK 1.7,它在JDK 1.6的基础上做了进一步的优化,

JAVA Collection 源码分析(一)之ArrayList

到今天为止,差不多已经工作一年了,一直在做的是javaweb开发,一直用的是ssh(sh)别人写好的框架,总感觉自己现在高不成低不就的,所以就像看看java的源码,顺便学习一下大牛的思想和架构,read and write一直是提高自己编程水平的不二法门,写博客只是记录自己的学习历程,方便回顾,写的不好的地方,请多多包含,不喜勿喷,好了废话少说,现在让我们开始我们的历程把,Let's go!!!!!!!! 想看源码无从下手,不知道有没有跟我一样感觉的人们,今天用Intellij发现了可以找出类与

java集合类源码剖析

java集合类源码剖析 hashmap 底层实现 HashMap.Entry数组,数组+拉链 static class Entry<K,V> implements Map.Entry<K,V> { final K key; V value; Entry<K,V> next; final int hash; } Entry对象代表了HashMap中的一个元素(键值对) hashCode相同(碰撞)的元素将分配到Entry数组的同一个桶中 同一个桶中的Entry对象由nex

JAVA Collection 源码分析(二)之SubList

昨天我们分析了ArrayList的源码,我们可以看到,在其中还有一个类,名为SubList,其继承了AbstractList. // AbstractList类型的引用,所有继承了AbstractList都可以传进来 private final AbstractList<E> parent; // 这个是其实就是parent的偏移量,从parent中的第几个元素开始的 private final int parentOffset; private final int offset; int s

Java 集合源码分析(一)HashMap

目录 Java 集合源码分析(一)HashMap 1. 概要 2. JDK 7 的 HashMap 3. JDK 1.8 的 HashMap 4. Hashtable 5. JDK 1.7 的 ConcurrentHashMap 6. JDK 1.8 的 ConcurrentHashMap 7. 最后补充一下 HashMap 中的一些属性和方法 附:更这个系列感觉自己像是又挖了一个坑??,不过趁自己刚好工作不太忙,有空闲期,静下心来研究学习源码也是一件很值得做的事,自己尽量会把这个坑填完??.

超赞!推荐一个专注于Java后端源码分析的Github项目!

大家好,最近有小伙伴们建议我把源码分析文章及源码分析项目(带注释版)放到github上,这样小伙伴们就可以把带中文注释的源码项目下载到自己本地电脑,结合源码分析文章自己本地调试,总之对于学习开源项目源码会更方便. 因此下面提供[源码笔记]的Github地址,若您觉得不错,欢迎Star点亮哦: Github主页:https://github.com/yuanmabiji 源码分析文章:https://github.com/yuanmabiji/Java-SourceCode-Blogs Sprin