浅谈Vector
浅谈Vector
在之前的文章中,我们已经说过线程不安全的ArrayList和LinkedList,今天我们来讲讲一个线程安全的列表容器,他就是Vector,他的底层和ArrayList一样使用数组来实现,不过不同于ArrayList的线程不安全,Vector中的公开方法基本都是带有synchronized关键字的,虽然有些方法是非同步的,但内部总是会调用同步的方法保证整个方法的线程安全,即使是subList方法返回的子列表也是通过Collections类的synchronizedList来保证返回的子列表也是线程安全的:
public synchronized List<E> subList(int fromIndex, int toIndex) {
return Collections.synchronizedList(super.subList(fromIndex, toIndex), this);
}
下面我们来介绍Vector的构造方法,Vector为我们提供了四种构造方法,前三种,基本就是无参调用单参,并传递一个默认容量值,单参调用双参,并传递一个默认容量值
Vector();
public Vector() {
//调用单参的构造方法,并传递一个初始容量值10
this(10);
}
Vector(int initialCapacity);
public Vector(int initialCapacity) {
//调用双参的构造方法,并传递一个默认增量值0,增量值为0,代表每次扩容,容量会直接翻倍
this(initialCapacity, 0);
}
Vector(int initialCapacity, int capacityIncrement);
public Vector(int initialCapacity, int capacityIncrement) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
this.elementData = new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
}
第四种构造方法,则是根据传入的集合对象来初始化矢量列表的元素
Vector(Collection<? extends E> c);
public Vector(Collection<? extends E> c) {
elementData = c.toArray();
elementCount = elementData.length;
// c.toArray might (incorrectly) not return Object[] (see 6260652)
//如果通过toArray方法转换得到的数组类型不是Object[],则进行二次转化
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
}
在方法讲解之前,我们先来看看Vector的扩容机制,Vector提供了一个公开方法ensureCapacity(int minCapacity),通过该方法你可以传入一个列表需要的最小容量值(但最终生成的新容量可能并不是这个值),然后做一个简单的校验,进一步调用内部私有的ensureCapacityHelper(int minCapacity)方法进行进一步判断,如果该值小于列表当前的列表容量(非列表元素总数),不会进入到扩容方法grow中,进入grow方法后就开始了具体的扩容流程,具体请看下面的源码:
public synchronized void ensureCapacity(int minCapacity) {
if (minCapacity > 0) {
modCount++;
ensureCapacityHelper(minCapacity);
}
}
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;
//按内置规则扩容获得新的容量值,如果增量变量为0,容量翻倍,否则增加增量变量指定的增量值
int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity);
//将新的容量值与传入的最小容量作比较,如果最小容量值大于新的容量值,则将最小容量值作为新的容量值,否则使用内置扩容规则获得的容量值
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//最后将容量值与数组最大容量值(最大整型值-8)做比较
//数组作为一个对象,需要一定的内存存储对象头信息,对象头信息最大占用内存不可超过8字节
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
//使用新容量和原列表生成新的列表并将元素进行拷贝,内部最终调用System.arraycopy方法进行元素拷贝
elementData = Arrays.copyOf(elementData, newCapacity);
}
讲完Vector的扩容规则,下面正式进入Vector中方法的讲解
add(E element); addElement(E element);
这个两个方法都是往矢量列表尾部插入新的元素,都是同步方法,不同点是add的返回值为布尔类型,而addElement没有返回值
add(int index, E element); insertElementAt(E element, int index);
这两个方法可以说是完全一致,在add方法内只是进行了insertElementAt方法的调用,虽然add是非同步方法,但insertElementAt是一个同步方法
addAll([int index,] Collection<? extends E> c);
该方法用于往矢量列表中存入集合中的所有元素,该方法存在单参和双参两个重载方法,都是同步方法,单参方法直接往尾部插入,双参方法可以在指定索引位置插入
remove(int index);
该方法用于删除矢量列表中指定索引位置的值,并返回被删除的元素,该方法是同步方法
remove(Object o); removeElement(Object o); removeElementAt(int index);
这三个方法都是用于删除矢量列表中的元素,其中remove是非同步的,其余两个方法都是同步的,但在remove方法调用了同步的removeElement方法,在removeElement方法中先是通过indexOf方法查找待删除元素的索引,找到则调用removeElementAt方法删除指定索引位置的元素值
removeAll(Collection<?> c)
该方法用于删除传入集合中指定的所有元素,是一个同步方法
retainAll(Collection<?> c);
该方法用于保留传入集合中指定的所有元素,即删除指定集合之外的所有元素,该方法是一个同步方法
clear(); removeAllElements();
这两个方法都是用于删除矢量列表中的所元素,其中clear方法是非同步的,内部调用了同步的removeAllElements方法
removeRange(int fromIndex, int toIndex);
该方法用于移除矢量列表中指定索引范围的所有元素,该方法是一个同步方法
removeIf(Predicate<? super E> filter);
该方法用于移除矢量列表中符合指定条件的元素,该方法是一个同步方法,下面使用匿名内部类和Lambda做一个简单的使用演示:
Vector<Integer> list = new Vector<>();
list.add(1);list.add(2);list.add(3);list.add(4);list.add(5);
System.out.println(list);
//如果不会使用Lambda表达式,则需要new Predicate接口对象并实现内部的test方法
list.removeIf(x -> x < 3);
System.out.println(list);
//对应的运行结果
[1, 2, 3, 4, 5]
[3, 4, 5]
set(int index, E element); setElementAt(E element, int index);
这两个方法都是用于替换矢量列表中指定索引位置的元素值,都是同步方法,不同点是set方法返回被替换的元素值,而setElementAt没有返回值
replaceAll(UnaryOperator operator);
该方法用于对矢量列表中的所有元素进行指定钩子函数的操作,并且会保存对元素所做的修改,该方法是一个同步方法,下面使用匿名内部类结合Lambda表达式做一个简单的使用演示:
Vector<Integer> list = new Vector<>();
list.add(1);list.add(2);list.add(3);list.add(4);list.add(5);
System.out.println(list);
//或者使用UnaryOperator接口创建匿名内部类,并实现apply方法亦可
list.replaceAll(x -> x + 2);
System.out.println(list);
//对应的运行结果
[1, 2, 3, 4, 5]
[3, 4, 5, 6, 7]
forEach()
该方法用于对矢量列表中的所有元素进行指定钩子函数的操作,但是不会保存对元素所做的修改,该方法是一个同步方法,下面做简单演示:
Vector<Integer> list = new Vector<>();
list.add(1);list.add(2);list.add(3);list.add(4);list.add(5);
System.out.println(list);
//或者使用Consumer接口创建匿名内部类,并实现accept方法亦可
list.forEach(x -> System.out.println(x += 2));
System.out.println(list);
//对应的运行结果
[1, 2, 3, 4, 5]
3
4
5
6
7
[1, 2, 3, 4, 5]
get(int index); elementAt(int index);
这两个方法是一样的,用于返回矢量列表中指定位置的元素值,都是同步方法
elements();
该方法用于返回矢量列表的枚举对象,该方法是一个同步方法,可以使用返回的枚举对象进行简单迭代遍历,下面是简单应用:
Vector<Integer> list = new Vector<>();
list.add(1);list.add(2);list.add(3);list.add(4);list.add(5);
Enumeration<Integer> elements = list.elements();
while (elements.hasMoreElements()){
System.out.println(elements.nextElement());
}
firstElement(); lastElement();
这两个方法分别用于返回矢量列表中的首元素和尾元素,都是同步方法
indexOf(Object o); lastIndexOf(Object o);
这两个方法分别用于返回矢量列表中第一次出现和最后一次出现指定元素的索引值,都是同步方法
lastIndexOf(Object o, int index);
该方法在lastIndexOf(Object o)的基础上添加了一个索引值,用于在指定索引值之前的位置查找最后一次出现指定元素的索引值,该方法是同步方法
iterator();
该方法用于返回矢量列表的普通迭代器对象,迭代器提供了hasNext,next,remove,forEachRemaining方法用于对元素进行操作,iterator方法是是一个同步方法
listIterator([int index]);
该方法用于返回矢量列表的增强迭代器对象,提供了普通迭代器的所有功能,此外还有hasPrevious,nextIndex,previousIndex,previous,set,add方法,而且还可以通过index参数指定起始迭代位置,listIterator方法是一个同步方法
spliterator();
该方法用于将矢量列表转化为可分割的数组对象,转化后的对象可以多次调用trySplit进行分割(五五分成),适合多线程的方式对大型矢量列表进行操作,简单演示拆分过程:
Vector<Integer> list = new Vector<>();
list.add(1);list.add(2);list.add(3);list.add(4);list.add(5);
list.add(6);list.add(7);list.add(8);list.add(9);list.add(0);
Spliterator<Integer> part1 = list.spliterator();
Spliterator<Integer> part2 = part1.trySplit();
Spliterator<Integer> part3 = part1.trySplit();
Spliterator<Integer> part4 = part2.trySplit();
part1.forEachRemaining(x-> System.out.print(x+" "));
System.out.println();
part2.forEachRemaining(x-> System.out.print(x+" "));
System.out.println();
part3.forEachRemaining(x-> System.out.print(x+" "));
System.out.println();
part4.forEachRemaining(x-> System.out.print(x+" "));
//对应的操作结果
8 9 0
3 4 5
6 7
1 2
capacity();
该方法用于返回矢量列表的容量值(elementData.length),该方法是一个同步方法
clone();
该方法用于返回一个矢量列表的浅克隆对象,该方法是同步方法
contains(Object o);
该方法用于判断矢量列表中是否含有指定元素,该方法是一个非同步方法,但内部调用同步的indexOf方法
containsAll(Collection<?> c);
该方法用于判断矢量列表中是否包含传入集合的所有元素,该方法是一个同步方法
copyInto(Object[] array);
该方法用于将矢量列表的全部元素值拷贝到传入的数组中,该方法是一个同步方法
equals(Object o);
该方法用于判断传入元素是否与当前元素相等(值相等,不一定非要是地址相等),该方法是同步方法
isEmpty();
该方法用于判断矢量列表中是否存在元素,主要根据elementCount属性值来判断,该方法是同步方法
setSize(int size);
该方法用于将矢量列表的元素总数控制在传入的size之内,如果size大于当前列表元素总数(elementCount),则将elementCount-size范围的null当做列表元素(从这里可以看出矢量列表中的元素存在与否不能根据是否为null来判断,而需要根据elementCount来判断),如果传入的size小于列表元素总数,则将size-elementCount的值都置为null,最后都将elementCount=size值,该方法是一个同步方法
size();
该方法用于返回矢量列表的元素总数(elementCount),该方法是一个同步方法
sort(Comparator<? super E> c);
该方法用于将矢量列表里的所有元素按照钩子函数的规则进行排序,该方法是一个同步方法,下面对该方法做简单演示:
Vector<Integer> list = new Vector<>();
list.add(1);list.add(4);list.add(5);list.add(2);list.add(3);
list.add(8);list.add(9);list.add(0);list.add(6);list.add(7);
System.out.println(list);
//或者使用Comparator接口创建匿名内部类,并实现compare方法亦可
list.sort((o1,o2) -> o1 - o2);
System.out.println(list);
subList(int fromIndex, int toIndex);
该方法用于返回当前矢量列表指定范围内的子列表对象,该方法是一个同步方法,要注意的是最终返回的列表对象依旧是整个矢量列表对象,不过是添加了偏移量属性,所以对子列表的操作都会反映到父列表中
toArray(T[] a);
该方法用于获取矢量列表的数组对象,并转化为参数对应的数组类型,该方法是一个同步方法,以下为该方法的简单使用:
//如果直接调用list.toArray()方法,等同于list.toArray(new Object[0]);
String[] strs = list.toArray(new String[0]);
trimToSize();
该方法用于将矢量列表的容量调整为列表元素总数,调整中会生成新的数组对象,该方法为同步方法
如果对你有帮助,点个赞,或者打个赏吧,嘿嘿
整理不易,请尊重博主的劳动成果
浅谈Vector的更多相关文章
- 浅谈 Vector
目录 浅谈Vector 1.容器基本操作 2.vector 初始化 3.vector的赋值与swap 4.vector的增删改除 1.增加元素 2.访问元素 3.删除元素 4.元素的大小 浅谈Vect ...
- 浅谈Vector、ArrayList、LinkedList
下图是Collection的类继承图 从图中可以看出:Vector.ArrayList.LinkedList这三者都实现了List 接口.所有使用方式也很相似,主要区别在于实现方式的不同,所以对不同的 ...
- 由jtable浅谈vector<vector<Object>>的用法(转自a718515028的专栏)
以前只用过vector<Object> ,但是在做从数据库导出数据放到jtable中时,发现还有个vector<vector<Object>>的用法. 先说jta ...
- 浅谈C++ STL vector 容器
浅谈C++ STL vector 容器 本篇随笔简单介绍一下\(C++STL\)中\(vector\)容器的使用方法和常见的使用技巧.\(vector\)容器是\(C++STL\)的一种比较基本的容器 ...
- 浅谈JAVA集合框架
浅谈JAVA集合框架 Java提供了数种持有对象的方式,包括语言内置的Array,还有就是utilities中提供的容器类(container classes),又称群集类(collection cl ...
- C++ STL中的常用容器浅谈
STL是C/C++开发中一个非常重要的模板,而其中定义的各种容器也是非常方便我们大家使用.下面,我们就浅谈某些常用的容器.这里我们不涉及容器的基本操作之类,只是要讨论一下各个容器其各自的特点.STL中 ...
- 浅谈Java的集合框架
浅谈Java的集合框架 一. 初识集合 重所周知,Java有四大集合框架群,Set.List.Queue和Map.四种集合的关注点不同,Set 关注事物的唯一性,List 关注事物的索引列表,Q ...
- 浅谈java类集框架和数据结构(2)
继续上一篇浅谈java类集框架和数据结构(1)的内容 上一篇博文简介了java类集框架几大常见集合框架,这一篇博文主要分析一些接口特性以及性能优化. 一:List接口 List是最常见的数据结构了,主 ...
- 浅谈压缩感知(二十四):压缩感知重构算法之子空间追踪(SP)
主要内容: SP的算法流程 SP的MATLAB实现 一维信号的实验与结果 测量数M与重构成功概率关系的实验与结果 SP与CoSaMP的性能比较 一.SP的算法流程 压缩采样匹配追踪(CoSaMP)与子 ...
随机推荐
- beautifulsoup实现文章截取和脚本攻击
引子:现在我们所写的所有高大上,炫酷的网页,在数据库中是如何存储的呢?其实数据库中存储的所有高大上的文章都是存的html,然后我们平时看的写的都是由于编辑器的原因,在编辑器内部做了转换,所以我们可以直 ...
- 【数据结构和算法】001 单链表 LinkedList
一.单链表(LinkedList)介绍和内存布局 链表是有序的列表,它在内存中的实际存储结构如下: 看上去虽然无序,但他是靠灭个链表节点元素的地址和next域来分清首尾相连的顺序,如下图所示,由头指针 ...
- mysql系列-⼀条SQL查询语句是如何执⾏的?
⼀条SQL查询语句是如何执⾏的? ⼤体来说,MySQL 可以分为 Server 层和存储引擎层两部分 Server 层 Server 层包括连接器.查询缓存.分析器.优化器.执⾏器等,涵盖 MySQL ...
- C语言自学网官方微信相关功能使用方法
一.微信扫描关注微信公众账号(C语言自学网),我们会不定时更新关于编程的技术文章和相关资讯,了解大佬的成长之路. 二.回复“C语言学习资料”,将显示由我们精心整理的全套C语言学习资料的下载地址及链接. ...
- 5分钟配置好你的AI开发环境
作者 | Revolver 无论是第一次设置TensorFlow的新手数据科学爱好者,还是使用TB级数据的经验丰富的AI工程师,安装库.软件包或者框架总是一个困难又繁琐的过程.但是像Docker这样的 ...
- JAVA——桌球游戏(动画)
跟着视频敲得 ,虽然不是自己的思路 ,不过对代码多了一点了解:涉及到继承类 主函数:创建一个BallGame对象,调用一个launchFrame函数 : launchFrame函数:严格来说是方法 , ...
- PyCharm3.0 快捷键
1.编辑(Editing) Ctrl + Space 基本的代码完成(类.方法.属性)Ctrl + Alt + Space 快速导入任意类Ctrl + Shift + Enter 语句完 ...
- LFU五种实现方式,从简单到复杂
前言 最近刷力扣题,对于我这种 0 基础来说,真的是脑壳疼啊.这个月我估计都是中等和困难题,没有简单题了. 幸好,力扣上有各种大牛给写题解.看着他们行云流水的代码,真的是羡慕不已.让我印象最深刻的就是 ...
- Java实验五参考答案
1.找错误 btOK.setOnAction( new EventHandler<ActionEvent> { public void handle (ActionEvent e) { S ...
- 1053 Path of Equal Weight (30分)(并查集)
Given a non-empty tree with root R, and with weight Wi assigned to each tree node Ti. The weig ...