Vector源码解读
1.背景
阅读源码是提高编程技能的有效方式...
面试中也经常问到源码相关的问题.....
2.源码解读
在解读Vector时大家可以先解读ArrayList,因为这个两个的逻辑几乎是一样的....
ArrayList源码解读:https://www.cnblogs.com/newAndHui/p/16101626.html
区别在于
1.Vector的很多方法都是同步的即线程安全的,二ArrayList的很多方法时线程非同步的;
2.Vector扩容默认是原来的1倍,二ArrayList默认是按照原来的1.5倍扩容;
3.Vectory对象创建时默认数组长度为10,而ArrayList对象创建时是一个空数组,在添加第一个元素是才设置数组长度为10
阅读源码前自己写一个与Vector功能差不多的对象MyVector,相信你看懂了MyVector,那么Vector你就自然懂了...
package com.ldp.collection.my; import java.util.AbstractList;
import java.util.Arrays;
import java.util.List;
import java.util.RandomAccess; /**
* @author 姿势帝-博客园
* @address https://www.cnblogs.com/newAndHui/
* @WeChat 851298348
* @create 04/05 10:51
* @description
*/
public class MyVector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
private static final long serialVersionUID = -2767605614048989439L;
protected Object[] elementData; // 存放元素的数组对象
protected int elementCount; // 存放的元素个数
protected int capacityIncrement; // 数组扩容时的扩容量,默认为0,表示安装原来的1倍扩容,10扩容一次后为20
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;// 数组的最大容量 /**
* 无参数构造方法,默认容量为10
*/
public MyVector() {
this(10);
} /**
* 自定义容量的构造方法
*/
public MyVector(int initialCapacity) {
this(initialCapacity, 0);
} /**
* 自定义容量 和 扩容数的构造方法
*
* @param initialCapacity 数组长度
* @param capacityIncrement 扩容时的增加长度,默认为0,安装原来的1倍扩容
*/
public MyVector(int initialCapacity, int capacityIncrement) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: " +
initialCapacity);
this.elementData = new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
} /**
* 线程安全的,所以很多操作方法都是加了 synchronized 关键字的
*/
@Override
public synchronized boolean add(E e) {
// 累加修改次数
modCount++;
// 确定容量
ensureCapacityHelper(elementCount + 1);
// 在原来的元素后面加一个元素
elementData[elementCount++] = e;
return true;
} private void ensureCapacityHelper(int minCapacity) {
// 当最小需要的容量大于数组长度时进行扩容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
} private void grow(int minCapacity) {
// 原来的容量
int oldCapacity = elementData.length;
// 新的容量,capacityIncrement=0时,newCapacity=oldCapacity+oldCapacity,即按照原来的1倍扩容
int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity);
// 加一倍后长度还是不够,则用传递过来的数值minCapacity(addAll来说,就是原长度+新集合长度)
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
// 超出最大值时计算
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 执行扩容
elementData = Arrays.copyOf(elementData, newCapacity);
} private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
} @Override
public synchronized E get(int index) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index); return elementData(index);
} @SuppressWarnings("unchecked")
E elementData(int index) {
return (E) elementData[index];
} @Override
public synchronized int size() {
return elementCount;
}
}
完美!
Vector源码解读的更多相关文章
- jdk1.8.0_45源码解读——ArrayList的实现
jdk1.8.0_45源码解读——ArrayList的实现 一.ArrayList概述 ArrayList是List接口的可变数组的实现.实现了所有可选列表操作,并允许包括 null 在内的所有元素. ...
- Input源码解读——从"Show tabs"开始
Input源码解读--从"Show tabs"开始 本文基于Android T版本源码,梳理当用户在开发者选项中开启Show tabs功能后显示第点按操作的视觉反馈的原理,来进一步 ...
- SDWebImage源码解读之SDWebImageDownloaderOperation
第七篇 前言 本篇文章主要讲解下载操作的相关知识,SDWebImageDownloaderOperation的主要任务是把一张图片从服务器下载到内存中.下载数据并不难,如何对下载这一系列的任务进行设计 ...
- SDWebImage源码解读 之 NSData+ImageContentType
第一篇 前言 从今天开始,我将开启一段源码解读的旅途了.在这里先暂时不透露具体解读的源码到底是哪些?因为也可能随着解读的进行会更改计划.但能够肯定的是,这一系列之中肯定会有Swift版本的代码. 说说 ...
- SDWebImage源码解读 之 UIImage+GIF
第二篇 前言 本篇是和GIF相关的一个UIImage的分类.主要提供了三个方法: + (UIImage *)sd_animatedGIFNamed:(NSString *)name ----- 根据名 ...
- SDWebImage源码解读 之 SDWebImageCompat
第三篇 前言 本篇主要解读SDWebImage的配置文件.正如compat的定义,该配置文件主要是兼容Apple的其他设备.也许我们真实的开发平台只有一个,但考虑各个平台的兼容性,对于框架有着很重要的 ...
- SDWebImage源码解读_之SDWebImageDecoder
第四篇 前言 首先,我们要弄明白一个问题? 为什么要对UIImage进行解码呢?难道不能直接使用吗? 其实不解码也是可以使用的,假如说我们通过imageNamed:来加载image,系统默认会在主线程 ...
- SDWebImage源码解读之SDWebImageCache(上)
第五篇 前言 本篇主要讲解图片缓存类的知识,虽然只涉及了图片方面的缓存的设计,但思想同样适用于别的方面的设计.在架构上来说,缓存算是存储设计的一部分.我们把各种不同的存储内容按照功能进行切割后,图片缓 ...
- SDWebImage源码解读之SDWebImageCache(下)
第六篇 前言 我们在SDWebImageCache(上)中了解了这个缓存类大概的功能是什么?那么接下来就要看看这些功能是如何实现的? 再次强调,不管是图片的缓存还是其他各种不同形式的缓存,在原理上都极 ...
- AFNetworking 3.0 源码解读 总结(干货)(下)
承接上一篇AFNetworking 3.0 源码解读 总结(干货)(上) 21.网络服务类型NSURLRequestNetworkServiceType 示例代码: typedef NS_ENUM(N ...
随机推荐
- redis zset 延迟合并任务处理
redis zset 延迟合并任务处理 @Autowired public RedisTemplate redisTemplate; ##1.发送端:在接口中收集任务ID,累计时间段之后,合并处理. ...
- 记一次 Edge 及谷歌 Chrome 浏览器兼容性冲突的解决
目录 记一次 Edge 及谷歌 Chrome 浏览器兼容性冲突的解决 浏览器兼容性冲突症状 解决方法 1. 把本机和远程的 8235 和 8237 端口屏蔽,包括 TCP 和 UDP 端口 2. 在 ...
- idea远程debug(物理机、docker、k8s)
IDEA远程DEBUG 1:物理机部署的Springboot项目远程DEBUG 1.1:idea配置 点击"Edit Configurations",再点击+,选择Remote, ...
- QT学习:00 介绍
--- title: framework-cpp-qt-00-介绍 date: 2020-04-08 15:41:54 categories: tags: - c/c++ - qt --- 章节描述: ...
- python爬虫-xpath基础
# 准备一个html格式文档 doc = ''' <div> <ul> <li class="item-0"><a href=" ...
- spark共享变量---广播变量和累加变量
从三个方面来分析:1.什么时候使用,2.原理是什么3.性能上有什么优化 累加变量:--(自定义累加器很重要) 使用场景:累加器的一个常见用途是在调试时对作业执行过程中的事件进行计数,如:统计日志中空行 ...
- 使用定时器:在logs目录,每两分钟产生一个文件
1.使用定时器:在logs目录,每两分钟产生一个文件(文件格式为:201711151323.log.201711151323.log.2017111513xx.log ...思路:定时器定时调用she ...
- Go 使用原始套接字捕获网卡流量
Go 使用原始套接字捕获网卡流量 Go 捕获网卡流量使用最多的库为 github.com/google/gopacket,需要依赖 libpcap 导致必须开启 CGO 才能够进行编译. 为了减少对环 ...
- 推荐几款个人喜欢的IDEA开发工具主题【更舒适的开发】
IDEA,全称 IntelliJ IDEA ,是Java语言的集成开发环境,IDEA在业界被公认为是最好的 java 开发工具之一,尤其在智能 代码助手.代码自动提示.重构.J2EE支持. Ant . ...
- K8S 中的 CRI、OCI、CRI shim、containerd
哈喽大家好,我是咸鱼. 好久没发文了,最近这段时间都在学 K8S.不知道大家是不是和咸鱼一样,刚开始学 K8S.Docker 的时候,往往被 CRI.OCI.CRI shim.containerd 这 ...