Vector 类提供了实现可增长数组的功能,与ArrayList类似,会对比这两个进行讲解。
属性:
protected Object[] elementData;
存储数据对象,与ArrayList一样,底层存储都是数组对象
protected int elementCount;
vector数据元素个数,小于等于elementData,ArrayList用的是size
protected int capacityIncrement;
vector数组容量扩容是增长大小,默认为0,ArrayList没有该参数,每次按照0.5的进行扩展。
创建
VectorAPI提供了三种构造方法
//时间调用构造方法 public Vector(int initialCapacity, int capacityIncrement) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); //实例化数组对象,对象容量初始的大小,默认为10,扩容增长capacityIncrement为0 this.elementData = new Object[initialCapacity]; this.capacityIncrement = capacityIncrement; } public Vector(int initialCapacity) { this(initialCapacity, 0); } public Vector() { this(10); }
对于默认new Vector来说会创建一个默认存储容量为10的数组对象,扩容增长为0,元素个数elementCount初始化为0。
增加元素
两种方式,一为直接插入,二为插入到指定索引位置。
public synchronized boolean add(E e) { modCount++; //验证对象数组的容量,如果容量不够,先进行扩容 ensureCapacityHelper(elementCount + 1); //将elementCount索引位置的填充元素,elementCount自加1 elementData[elementCount++] = e; return true; } // private void ensureCapacityHelper(int minCapacity) { //原有的对象数组的容量 int oldCapacity = elementData.length; //插入的索引位置大于原有的读写数组的容量进行扩容 if (minCapacity > oldCapacity) { Object[] oldData = elementData; //如果扩容增量大于0,则新的容量为原有容量+扩容增量,小于0,则按照原有容量扩大一倍。 int newCapacity = (capacityIncrement > 0) ? (oldCapacity + capacityIncrement) : (oldCapacity * 2); //如果新的容量还是小于索引,直接将索引赋值给新容量 if (newCapacity < minCapacity) { newCapacity = minCapacity; } //按照新容量进行扩容 elementData = Arrays.copyOf(elementData, newCapacity); } //将元素插入到指定索引 public void add(int index, E element) { insertElementAt(element, index); } public synchronized void insertElementAt(E obj, int index) { modCount++; //index大于当前数组元素个数量直接抛出异常 if (index > elementCount) { throw new ArrayIndexOutOfBoundsException(index + " > " + elementCount); } //验证对象数组的容量,如果容量不够,先进行扩容 ensureCapacityHelper(elementCount + 1); //将对象数组的索引index到elementCount-1对应的数据进行后移 System.arraycopy(elementData, index, elementData, index + 1, elementCount - index); //将对象数组索引位置为index填充为插入值 elementData[index] = obj; //元素个数+1 elementCount++; }
(1):直接插入,对象数组容量够,直接插入到elementCount所对应的索引位置。对象数组容量不够,先进行数组扩容,扩容默认为原对象数组容量的1倍,再索引位置为elementCount进行填充。
(2):插入指定位置,对象数组容量够,进行数组拷贝,拷贝的个数为elementCount-index,对象数组容量不够,先进行扩容,再进行拷贝。
对于NULL值,和重复值也没有进行处理。
读取元素
public synchronized E get(int index) { //大于数组元素个数直接抛出异常 if (index >= elementCount) throw new ArrayIndexOutOfBoundsException(index); //取对应索引的元素 return (E)elementData[index]; }
读取元素比较简单,直接获取对象数组对应索引的值。
删除
//按照索引删除元素 public synchronized E remove(int index) { modCount++; //index大于等于elementCount抛出异常 if (index >= elementCount) throw new ArrayIndexOutOfBoundsException(index); //保存当前索引的旧值 Object oldValue = elementData[index]; //移动元素个数 int numMoved = elementCount - index - 1; //移动元素大于0,将索引index+1到elementCount-1前移一位 if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); //将elementCount-1,并将索引位置为elementCount-1设置为null elementData[--elementCount] = null; // Let gc do its work return (E)oldValue; }
删除涉及到数组的前移,前移的数据范围为删除索引的值+1到size-1的元素。注意我们发现删除并未和写入时一样进行对象数组的大小的自动收缩【即存储容量未发生变化】。这个和ArrayList一致。
按照元素值进行删除
public boolean remove(Object o) { return removeElement(o); } public synchronized boolean removeElement(Object obj) { modCount++; //获取索引位置 int i = indexOf(obj); //索引位置大于1进行删除 if (i >= 0) { //删除指定索引的元素 removeElementAt(i); return true; } return false; } public synchronized void removeElementAt(int index) { modCount++; if (index >= elementCount) { throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount); } else if (index < 0) { throw new ArrayIndexOutOfBoundsException(index); } // 移动的元素个数 int j = elementCount - index - 1; if (j > 0) { System.arraycopy(elementData, index + 1, elementData, index, j); } elementCount--; elementData[elementCount] = null; /* to let gc do its work */ }
按照元素值进行删除,会遍历对象数组,遍历元素个数为删除元素的索引index+1,且只会删除该元素值出现第一个。并且在删除时,对象数组会进行拷贝,拷贝元素个数为elementCount-index-1。
压缩对象数组存储容量
public synchronized void trimToSize() { modCount++; int oldCapacity = elementData.length; if (elementCount < oldCapacity) { elementData = Arrays.copyOf(elementData, elementCount); } }
已elementCount 进行压缩。
清空元素
public synchronized void removeAllElements() { modCount++; // Let gc do its work for (int i = 0; i < elementCount; i++) elementData[i] = null; elementCount = 0; }
清空主要进行两件事情:(1):将相关的数据元素设置为NULL值。(2):将elementCount 设置为0
可以发现Vector和ArrayList操作基本一致,并且相关的操作方式一致,当时还是有差异。
总结:
(1):Vector的实际存储对象为一个数组对象。没有容量大小,可以无限增加【默认扩展因子为1,否则为原来的容量+capacityIncrement】,只受JVM内存大小限制。
(2):Vector中可以包含重复的元素,并可以存储NULL值。
(3):Vector的相关方法都是线程安全的【与ArrayList存在差异,其他都一样】。
(4):Vector的索引访问和元素更新方面有着非常优秀的性能,因为不需要花费精力做范围检查,所以从Vector的末端添加元素,删除元素也有着非常优秀的性能,除非Vector的存储容量不足而需要扩展内部数组的长度【扩展的时候需要数组拷贝】。插入和删除数据需要一个数组的拷贝,需要拷贝的元素数量是Vector的元素长度(elementData-1)减去索引号,对插入来讲,插入元素到Vector的第一个元素位置的性能最差,插入到最后一个位子的性能最好,数组拷贝所需的时间会根据元素的数量增加而显著增加。
(5):Vector查找指定位置的数据时间为O(1),插入到指定位置的数据时间为O(elementData-index-1)。
(6):Vector插入大量的元素,提前指定Vector的大小,防止在插入过程Vector进行扩容。
(7):Vector按照元素值进行删除时,会遍历数组对象,并且会进行数组拷贝,时间为O(elementData+1)+O(elementData-index-1),可以计算总共花费O(elementData),遍历的对象+拷贝的对对象就等于元素个数。
(8):Vector删除时,不会调整原有的数组存储容量的大小即在数组存储容量扩容的后删除所用扩容数据后也不会调整整个数组容量大小,手工调用trimToSize进行调整。
相关推荐
ava基础 基础知识 面向对象基础 Java基本数据类型 string和包装类 final关键字特性 Java类和包 抽象类和接口 代码块和代码执行顺序 Java自动拆箱装箱里隐藏的秘密 ...Java集合详解8:Java集合类细节精讲 JavaWeb
### Java集合类详解总结 在Java编程中,集合框架(Collection Framework)是处理一组对象的强大工具,它提供了标准的数据结构来存储和操作这些对象。Java集合框架主要包括`Collection`、`Set`、`List`、`Queue`、`...
本文将深入讲解Java集合类,特别是Collection接口和其下的List、Set,以及Map接口中的几个重要实现类。 首先,我们来看Collection接口。Collection是最基本的集合接口,它代表一组Object,即它的元素。Collection...
本文将对Java集合框架中的Collection接口及其相关接口、类进行深入的探讨。 首先,Collection接口是所有单值容器的基础,它是Set、List和Queue接口的父接口。Collection接口定义了通用的操作方法,如`add()`用于...
`Vector`是Java集合框架中的一个类,它提供了一种线程安全的动态数组实现。与`ArrayList`不同,`Vector`在多线程环境中能确保数据的一致性和安全性,这主要得益于它的方法大多都是同步的(synchronized)。`Vector`...
Java集合类总结 Java集合详解:一文读懂ArrayList,Vector与Stack使用方法和实现原理 Java集合详解:Queue和LinkedList Java集合详解:迭代器,快速失败机制与比较器 Java集合详解:HashMap和HashTable Java集合详解...
Java集合框架是Java标准库的一部分,它提供了一系列的接口和类来存储和操作各种类型的对象集合。这些接口和类遵循一致的设计模式,使得开发人员可以方便地管理和操作数据。本文档将深入探讨Java集合框架的关键组成...
以上内容只是Java集合类面试题的一部分,实际面试中可能还会涉及到HashMap和Hashtable的区别、TreeSet的排序原理、迭代器的使用、并发集合(如ConcurrentHashMap和CopyOnWriteArrayList)的特性,以及如何根据具体...
Java集合是Java编程语言提供的一套用于数据存储和操作的接口与类的集合。根据Java集合框架,集合主要可以分为两大类:Collection...因此,深入学习和理解Java集合框架,对于提高Java开发的实战能力有着直接的积极影响。
`Vector`是Java集合框架的一部分,它是动态数组的实现,可以自动调整其大小。`Vector`与ArrayList类似,但它是线程安全的,适合多线程环境。`Vector`提供了一系列的方法,如`add()`用于添加元素,`remove()`用于删除...
`Vector`类是Java集合框架的一部分,位于`java.util`包中,它继承自`AbstractList`并实现了`List`接口,因此具备列表的所有特性。`Vector`的出现早于`ArrayList`,但在现代编程实践中,由于其线程安全的特性,往往被...
在本次实验中,我们深入学习了Java集合框架中的两个主要部分:List接口和Map接口,以及它们的主要实现类,并探讨了泛型的概念。 首先,我们了解了集合的概念,它是一个可以存储多个对象的容器。集合框架的体系结构...
在面试中,尤其对于大型公司,深入理解Java集合类是评估开发者技能的关键指标。以下是一些大公司常问的Java集合类面试题,以及相关的知识点详解: 1. **ArrayList与LinkedList的区别** - ArrayList基于动态数组,...
面试中,理解并能区分各种常见的Java集合类是一项基础但重要的技能。本文将深入探讨ArrayList、LinkedList、HashSet、HashMap等常见集合类之间的差异,以及它们在实际应用中的选择依据。 首先,我们从列表(List)...
本教程将聚焦于三个特定的集合类:`Vector`、`Stack`和`HashSet`,通过小型示例来深入理解它们的特点和用法。 首先,`Vector`是Java集合框架中的一个古老类,它与`ArrayList`类似,都用于存储可变大小的对象数组。`...
在面试过程中,对Java集合框架的理解程度是衡量一个程序员对Java集合类库掌握熟练程度的重要指标。了解集合框架的原理、特点、常用类及其实现的内部机制,对于通过Java集合相关的面试题至关重要。通过深入理解集合...
这些知识点主要涉及Java集合框架中的各种数据结构,如List、Set、Map等,并深入探讨了它们在实际应用中的特性与用途。 ### Java集合框架简介 Java集合框架是Java标准库的一个组成部分,它为存储和操作对象提供了...