安全的可增长数组结构

实现:
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. vue,elementUI切换主题,自定义主题

    本文介绍两种elementUI切换主题色的方法 项目示例:http://test.ofoyou.com/theme/ git代码:记得star哦,谢谢 1:官方提供的方法,直接修改scss文件达到修改 ...

  2. redis在项目中的使用(单机版、集群版)

    1.下载jar包:jedis-2.6.2.jar 2.代码: JedisDao.java: package com.test.www.dao; public interface JedisDao { ...

  3. asp.net 汉字转拼音的车祸现场

    asp.net 汉字转拼音 需求背景: 昨天遇到个问题,就是面对系统中集中性的要设置大批量的用户设置默认的用户名,密码,权限(角色),同时要求用户名是姓名的全拼,回头看看旁边那个哥们撸胳膊挽袖子准备一 ...

  4. 你不知道的JavaScript(七)delete操作符

    JS中的delete操作符不是太常用,容易被忽略,它的作用很简单,用来删除对象的属性或方法. <script type="text/javascript"> var p ...

  5. php获取当前月份的前(后)几个月

    //获取当前月份的前一月 function GetMonth($sign) { //得到系统的年月 $tmp_date=date("Ym"); //切割出年份 $tmp_year= ...

  6. tomcat更改日志路径

    共有2个地方需要更改. 1.   tomcat/conf/logging.properties 步骤1--查找:grep logs logging.properties 步骤2--替换:sed -i ...

  7. Collections库使用

    Date: 2019-05-27 Author: Sun Collections库 ​ Python拥有一些内置的数据类型,比如str, int, list, tuple, dict等, collec ...

  8. select选中值,传this

    <select onChange = "a(this)"></select> function a(obj){ $(obj).find("opti ...

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

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

  10. 微信小程序 分享海报

    const app = getApp(); const template = require('../../template/templates.js'); Page({ /** * 页面的初始数据 ...