安全的可增长数组结构

实现:
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. Kettle的四大不同环境工具

    不多说,直接上干货! kettle里有不同工具,分别用于ETL的不同阶段. 初学者,建议送Spoon开始.高手,是四大工具都会用. Sqoop: 图形界面工具,快速设计和维护复杂的ETL工作流.集成开 ...

  2. MyBatis数据持久化(五)数据源配置优化

    在前面的教程中,我们把数据库的驱动.用户名.密码等配置项全部写在 SqlMapConfig.xml中: <dataSource type="POOLED"> <p ...

  3. 初识Git(一)

    以前经常听到Git,作为一个菜鸟级自学选手从没有真正去了解Git,借刘铁猛老师在油管上的<对答如刘>初步认识了git,作以下记录. 1.初始化一个git管理的文件夹 首先我在我的电脑C盘P ...

  4. 查看锁表进程SQL语句

    查看锁表进程SQL语句   set pagesize 999 set line180 col ORACLE_USERNAME for a18 col OS_USER_NAME for a18 col ...

  5. Android Studio 开发安卓软件时下载的工程项目 Sync with gradle 失败

    Sync with gradle 失败的原因有很多,其中很多时候会遇到下载下来的工程同步失败,目前的经验来看下载的工程同步失败均是由于下图中的两个配置其中某个缺少了 google() 或者 jcent ...

  6. 深入了解JWT以及JWT的执行机制

    1.JWT以什么样的形式存在? eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9 ...

  7. 用TamperMonkey去掉cdsn中的广告

    最近CSDN需要登录后才能查看更多内容,有点影响心情 解决方案 添加一段书签 javascript:(function(){document.getElementById('article_conte ...

  8. JZOJ5787轨道(容斥+DP)

    JZOJ5787轨道 Description 2018年1月31日,152年一遇的超级大月全食在中国高空出现(没看到的朋友真是可惜),小B看到月食,便对月球的轨道产生了兴趣.他上网查重力加速度的公式, ...

  9. iview中单击行,使得checkbox状态的方法

    直接贴代码,这是一组jquery全选,全不选,反选代码 <!DOCTYPE html> <html lang="en"> <head> < ...

  10. pandas 2 选择数据

    from __future__ import print_function import pandas as pd import numpy as np np.random.seed(1) dates ...