安全的可增长数组结构

实现:
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源码学习的更多相关文章

  1. mongo源码学习(四)服务入口点ServiceEntryPoint

    在上一篇博客mongo源码学习(三)请求接收传输层中,稍微分析了一下TransportLayer的作用,这篇来看下ServiceEntryPoint是怎么做的. 首先ServiceEntryPoint ...

  2. Vector源码解析

    概要 学完ArrayList和LinkedList之后,我们接着学习Vector.学习方式还是和之前一样,先对Vector有个整体认识,然后再学习它的源码:最后再通过实例来学会使用它.第1部分 Vec ...

  3. [Java]Vector源码分析

    第1部分 Vector介绍 Vector简介 Vector也是基于数组实现的,是一个动态数组,其容量能自动增长.继承于AbstractList,实现了List, RandomAccess, Clone ...

  4. ArrayList、LinkedList和Vector源码分析

    ArrayList.LinkedList和Vector源码分析 ArrayList ArrayList是一个底层使用数组来存储对象,但不是线程安全的集合类 ArrayList的类结构关系 public ...

  5. [阿里DIN]从论文源码学习 之 embedding_lookup

    [阿里DIN]从论文源码学习 之 embedding_lookup 目录 [阿里DIN]从论文源码学习 之 embedding_lookup 0x00 摘要 0x01 DIN代码 1.1 Embedd ...

  6. Qt Creator 源码学习笔记04,多插件实现原理分析

    阅读本文大概需要 8 分钟 插件听上去很高大上,实际上就是一个个动态库,动态库在不同平台下后缀名不一样,比如在 Windows下以.dll结尾,Linux 下以.so结尾 开发插件其实就是开发一个动态 ...

  7. Java集合专题总结(1):HashMap 和 HashTable 源码学习和面试总结

    2017年的秋招彻底结束了,感觉Java上面的最常见的集合相关的问题就是hash--系列和一些常用并发集合和队列,堆等结合算法一起考察,不完全统计,本人经历:先后百度.唯品会.58同城.新浪微博.趣分 ...

  8. jQuery源码学习感想

    还记得去年(2015)九月份的时候,作为一个大四的学生去参加美团霸面,结果被美团技术总监教育了一番,那次问了我很多jQuery源码的知识点,以前虽然喜欢研究框架,但水平还不足够来研究jQuery源码, ...

  9. MVC系列——MVC源码学习:打造自己的MVC框架(四:了解神奇的视图引擎)

    前言:通过之前的三篇介绍,我们基本上完成了从请求发出到路由匹配.再到控制器的激活,再到Action的执行这些个过程.今天还是趁热打铁,将我们的View也来完善下,也让整个系列相对完整,博主不希望烂尾. ...

随机推荐

  1. xBIM 高级03 更改日志创建

    系列目录    [已更新最新开发文章,点击查看详细]  模型中发生的每一个变化都是事务的一部分,这是我们设计的核心.所有事务都是由 IModel 的实现创建的,并且从中被弱引用,因此当使用 using ...

  2. mysql 字符串的处理

    1.SUBSTRING 2.SUBSTRING_INDEX 3. right/left 4.POSITION sql实例 select left(right(SUBSTRING_INDEX(data_ ...

  3. ASP.NET MVC5 历史数据查询

    在TCX_1706项目中在历史数据库备份及历史数据查询的功能,历史数据包括历史采集数据查询和历史产品数据查询两个 在项目中如何查询历史库的历史表呢? 第一步:在配置文件中添加历史库的链接字符串 第二步 ...

  4. pthread_cleanup_push vs Autorelease VS 异常处理

    黑幕背后的Autorelease http://www.cnblogs.com/feng9exe/p/7239552.html objc_autoreleasePoolPush的返回值正是这个哨兵对象 ...

  5. ZBrush中常用笔刷综合简介

    单击左托盘的笔刷图标,弹出一个笔刷库,其中有许多常用笔刷,这也是许多初学者所头疼的问题,ZBrush的笔刷非常多,而且功能很强大,好多朋友不知道该选择哪一个笔刷进行雕刻.其实,在ZBrush的学习中我 ...

  6. Js jquery常用的身份证号码 邮箱电话等验证

    刷了很多博客,https://www.cnblogs.com/hao-1234-1234/p/6636843.html 只有这个比较靠谱.

  7. vue实现tab栏切换

    html <ul class="tab"> <li v-for="(item,index) in tabs" @click="tab ...

  8. (2016北京集训十四)【xsy1557】task

    题解: 限制可以看成图状结构,每个任务的对物品数量的影响可以看成权值,只不过这个权值用一个五元组来表示. 那么题意要求的就是最大权闭合子图,网络流经典应用. 代码: #include<algor ...

  9. HDU-2896 病毒侵袭 字符串问题 AC自动机

    题目链接:https://cn.vjudge.net/problem/HDU-2896 题意 中文题 给一些关键词和一个字符串,问字符串里包括了那几种关键词 思路 直接套模版 改insert方法,维护 ...

  10. HDU-2222 Keywords Search 字符串问题 AC自动机

    题目链接:https://cn.vjudge.net/problem/HDU-2222 题意 给一些关键词,和一个待查询的字符串 问这个字符串里包含多少种关键词 思路 AC自动机模版题咯 注意一般情况 ...