Vector源码学习
安全的可增长数组结构
实现:
1. 内部采用数组的方式。
1.1 添加元素,会每次校验容量是否满足, 扩容规则有两种,1.增加扩容补偿的长度,2.按照现有数组长度翻一倍。容量上限是Integer.MAX_VALUE。 copy使用Arrays.copy的api
1.2 删除元素
1.2.1 通过对象删除。遍历数组,删除第一个匹配的对象
1.2.3 通过下标删除。判断下标是否越界。
使用 System.arraycopy进行copy, 并将元素的最后一位设置为null.供gc回收
2. 内部是同步[modCount]
2.1 ArrayList数据结构变化的时候,都会将modCount++。
2.2 采用Iterator遍历的元素, next()会去检查集合是否被修改[checkForComodification],如果集合变更会抛出异常
类似于数据库层面的 乐观锁 机制。 可以通过 Iterator的api去删除元素
3. 数组结构,内部存储数据是有序的,并且数据可以为null,支持添加重复数据
4. 线程安全的, 关于数组的增删方法都采用了synchronized标注。
源码学习
// 自动增长的对象数组
public class Vector<E> { private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - ; // 元素数组
protected Object[] elementData; // 元素长度
protected int elementCount; // 扩容步长[增长容量]
protected int capacityIncrement; // 集合变更次数
private int modCount = ; public Vector(int initialCapacity) {
this(initialCapacity, ); // 10个长度,步长为0
} public Vector() {
this(); // 默认10个长度
} 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 synchronized boolean add(E element) { modCount++;
ensureCapacityHelper(elementCount + ); // 校验当前容器容量是否满足
elementData[elementCount++] = element;
return true;
} public synchronized void addElement(E obj) {
modCount++;
ensureCapacityHelper(elementCount + );
elementData[elementCount++] = obj;
} private void ensureCapacityHelper(int minCapacity) {
if (minCapacity - elementData.length > ) // 当前下标 > 数组长度
grow(minCapacity);
}
// 扩容方法
private void grow(int minCapacity) { int oldCapacity = elementData.length;
int newCapacity = oldCapacity + ((capacityIncrement > ) ?
capacityIncrement : oldCapacity); // 如果步长大于0, 每次扩容步长大小,否则按数组的长度翻一倍
if (newCapacity - minCapacity < )
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > )
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity); // 拷贝原来的内容 } private static int hugeCapacity(int minCapacity) {
if (minCapacity < ) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
} public boolean remove(Object o) {
return removeElement(o);
} public synchronized E remove(int index) {
modCount++;
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
E oldValue = elementData(index); int numMoved = elementCount - index - ;
if (numMoved > )
System.arraycopy(elementData, index+, elementData, index,
numMoved);
elementData[--elementCount] = null; // Let gc do its work return oldValue;
} // 从结尾开始查找元素
public synchronized int lastIndexOf(Object o) {
return lastIndexOf(o, elementCount-);
} // 指定位置,从结尾查找元素
public synchronized int lastIndexOf(Object o, int index) {
if (index >= elementCount)
throw new IndexOutOfBoundsException(index + " >= "+ elementCount); if (o == null) {
for (int i = index; i >= ; i--)
if (elementData[i]==null)
return i;
} else {
for (int i = index; i >= ; i--)
if (o.equals(elementData[i]))
return i;
}
return -;
} private synchronized boolean removeElement(Object obj) {
if (obj == null) {
for (int index = ; index < elementCount; index++)
if (elementData[index] == null) { // 删除 null
fastRemove(index);
return true;
}
} else {
for (int index = ; index < elementCount; index++)
if (obj.equals(elementData[index])) { // eqals比较
fastRemove(index);
return true;
}
}
return false;
} public synchronized void removeElementAt(int index) {
modCount++;
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " +
elementCount);
}
else if (index < ) {
throw new ArrayIndexOutOfBoundsException(index);
}
int j = elementCount - index - ;
if (j > ) {
System.arraycopy(elementData, index + , elementData, index, j);
}
elementCount--;
elementData[elementCount] = null; /* to let gc do its work */
} private void fastRemove(int index) {
modCount++;
int numMoved = elementCount - index - ; // 当前size - index - 1 数组从0开始
if (numMoved > )
System.arraycopy(elementData, index+, elementData, index,
numMoved); // system arraycopy
elementData[--elementCount] = null; // clear to let GC do its work gc回收 数组最后一个元素设置为null } public synchronized Iterator<E> iterator() {
return new Itr();
} private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -; // index of last element returned; -1 if no such
int expectedModCount = modCount; public boolean hasNext() {
// Racy but within spec, since modifications are checked
// within or after synchronization in next/previous
return cursor != elementCount;
} public E next() {
synchronized (Vector.this) {
checkForComodification();
int i = cursor;
if (i >= elementCount)
throw new NoSuchElementException();
cursor = i + ;
return elementData(lastRet = i);
}
} public void remove() {
if (lastRet == -)
throw new IllegalStateException();
synchronized (Vector.this) {
checkForComodification();
Vector.this.remove(lastRet);
expectedModCount = modCount;
}
cursor = lastRet;
lastRet = -;
} final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
} public synchronized E get(int index) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index); return elementData(index);
} public synchronized E elementAt(int index) {
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
} return elementData(index);
} @SuppressWarnings("unchecked")
E elementData(int index) {
return (E) elementData[index];
} public int size() {
return elementCount;
} }
Vector源码学习的更多相关文章
- mongo源码学习(四)服务入口点ServiceEntryPoint
在上一篇博客mongo源码学习(三)请求接收传输层中,稍微分析了一下TransportLayer的作用,这篇来看下ServiceEntryPoint是怎么做的. 首先ServiceEntryPoint ...
- Vector源码解析
概要 学完ArrayList和LinkedList之后,我们接着学习Vector.学习方式还是和之前一样,先对Vector有个整体认识,然后再学习它的源码:最后再通过实例来学会使用它.第1部分 Vec ...
- [Java]Vector源码分析
第1部分 Vector介绍 Vector简介 Vector也是基于数组实现的,是一个动态数组,其容量能自动增长.继承于AbstractList,实现了List, RandomAccess, Clone ...
- ArrayList、LinkedList和Vector源码分析
ArrayList.LinkedList和Vector源码分析 ArrayList ArrayList是一个底层使用数组来存储对象,但不是线程安全的集合类 ArrayList的类结构关系 public ...
- [阿里DIN]从论文源码学习 之 embedding_lookup
[阿里DIN]从论文源码学习 之 embedding_lookup 目录 [阿里DIN]从论文源码学习 之 embedding_lookup 0x00 摘要 0x01 DIN代码 1.1 Embedd ...
- Qt Creator 源码学习笔记04,多插件实现原理分析
阅读本文大概需要 8 分钟 插件听上去很高大上,实际上就是一个个动态库,动态库在不同平台下后缀名不一样,比如在 Windows下以.dll结尾,Linux 下以.so结尾 开发插件其实就是开发一个动态 ...
- Java集合专题总结(1):HashMap 和 HashTable 源码学习和面试总结
2017年的秋招彻底结束了,感觉Java上面的最常见的集合相关的问题就是hash--系列和一些常用并发集合和队列,堆等结合算法一起考察,不完全统计,本人经历:先后百度.唯品会.58同城.新浪微博.趣分 ...
- jQuery源码学习感想
还记得去年(2015)九月份的时候,作为一个大四的学生去参加美团霸面,结果被美团技术总监教育了一番,那次问了我很多jQuery源码的知识点,以前虽然喜欢研究框架,但水平还不足够来研究jQuery源码, ...
- MVC系列——MVC源码学习:打造自己的MVC框架(四:了解神奇的视图引擎)
前言:通过之前的三篇介绍,我们基本上完成了从请求发出到路由匹配.再到控制器的激活,再到Action的执行这些个过程.今天还是趁热打铁,将我们的View也来完善下,也让整个系列相对完整,博主不希望烂尾. ...
随机推荐
- http请求常出现的状态码
服务器返回的 响应报文 中第一行为状态行,包含了状态码以及原因短语,用来告知客户端请求的结果. 状态码 类别 原因短语 1XX Informational(信息性状态码) 接收的请求正在处理 2XX ...
- pagination使用说明
参考自张鑫旭 准备工作 下载jquery.min.js 下载jquery.pagination.js 下载pagination.css 开始敲代码 第一步,引入刚刚下载的三个文件 <link r ...
- servlet中Session的用法
## (1)什么是Session? 服务器端为了保存用户的状态而创建的一个特殊的对象(即session对象). 当浏览器第一次访问服务器时,服务器会创建session对象(该 ...
- (二)React简介
React简介 2-1: React v16 (React Fiber) React比Vue更灵活 Vue更简单 2-2 开发环境搭建 如何开始:(两种方式) 1.传统方式script标签引入.js文 ...
- Linux下重启mysql数据库的方法
原文地址:Linux下重启mysql数据库的方法作者:于士博的视频教程 方法一: 命令: [root@localhost /]# /etc/init.d/mysql start|stop|rest ...
- Mint-UI 没有样式?
如果用mint-ui组件,如toast没有样式,是因为没有映入全局样式和导入MintUI 方法如下: 1.安装 npm install mint-ui -S -S表示 --save 2.在main.j ...
- BZOJ 4896 [Thusc2016]补退选 (Trie树维护vector)
题目大意:略 这竟然是$thusc$的题... 先把询问里加入的串全拎出来,建出$Trie$树,$Trie$里每个节点都开一个$vector$记录操作标号,再记录操作数量$sum$ 然后瞎**搞搞就行 ...
- Windows 10用户可以快速移除U盘
新浪科技讯,北京时间 4 月 9 日上午消息,据美国科技媒体 The Verge 报道,微软再次证实,从 1809 版本的 Windows 10 开始,插入新闪存盘时“快速移除”(quick remo ...
- 【转】C#正则表达式教程和示例
[转]C#正则表达式教程和示例 有一段时间,正则表达式学习很火热很潮流,当时在CSDN一天就能看到好几个正则表达式的帖子,那段时间借助论坛以及Wrox Press出版的<C#字符串和正则表达式参 ...
- Android bluetooth介绍(一):基本概念及硬件接口
关键词:蓝牙硬件接口 UART PCM blueZ 版本号:基于android4.2之前版本号 bluez内核:linux/linux3.08系统:android/android4.1.3.4作者 ...