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也来完善下,也让整个系列相对完整,博主不希望烂尾. ...
随机推荐
- 创建ios界面的三步骤
1.加载数据 (包括懒加载和字典转模型等) 2.搭建界面 (常见的有九宫格算法和for循环的嵌套等) 3.实现用户交互 (通常用按钮实现)
- php获取当前月份的前(后)几个月
//获取当前月份的前一月 function GetMonth($sign) { //得到系统的年月 $tmp_date=date("Ym"); //切割出年份 $tmp_year= ...
- Vue this.$router.push、replace、go的区别
1.this.$router.push 描述:跳转到不同的url,但这个方法会向history添加一个记录,点击后会返回到上一个页面 用法 //字符串 this.$router.push('home' ...
- python中*号用法总结
python 中有很多地方用到星号,有时候会想知道这个*是干嘛用的,总结如下,有不当之处,还望不吝指出,谢谢.1.乘法: 在很多时候是用作乘法的,例如: In [90]: 2*7 Out[90]: 1 ...
- 15条JavaScript最佳实践【转】
本文档整理大部分公认的.或者少有争议的JavaScript良好书写规范(Best Practice).一些显而易见的常识就不再论述(比如要用对象支持识别判断,而不是浏览器识别判断:比如不要嵌套太深). ...
- 微信小程序微信支付的一些坑
使用的是Node.js作为后端 统一下单: appid:这里的appid是调起微信支付的appid mch_id:商户号,需要注意的是商户号要与appid对应 nonce_str:Math.rando ...
- java compare 时间排序
所有数据存进resultList中 Collections.sort(resultList, new Comparator<HashMap<String, Object>>() ...
- 教你用webpack搭一个vue脚手架[超详细讲解和注释!]
1.适用人群 1.对webpack知识有一定了解但不熟悉的同学. 2.女同学!!!(233333....) 2.目的 在自己对webpack有进一步了解的同时,也希望能帮到一些刚接触webpack的同 ...
- HTTP——学习笔记(5)
我们通信的过程中会有哪些风险?: 1.HTTP不会对通信方的身份进行确认 因为HTTP协议中的请求和相应不会对通信方进行确认,就是不管发送或接收信息的人是不是之前的人,都不妨碍信息的发送或接收. 缺点 ...
- Building a Space Station POJ 2031 【最小生成树 prim】
http://poj.org/problem?id=2031 Description You are a member of the space station engineering team, a ...