Jdk8集合源码解析---ArrayList
2019独角兽企业重金招聘Python工程师标准>>>
ArrayList的数据结构
ArrayList是一种线性数据结构,底层是动态数组实现的,与java中的数组相比,它的容量可以动态添加。
ArrayList的类结构
public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable{......}
ArrayList的主要成员变量
//默认容量
private static final int DEFAULT_CAPACITY = 10;private static final Object[] EMPTY_ELEMENTDATA = {};private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};//ArrayList存储数据的数组
transient Object[] elementData;//存储元素数目
private int size;//默认最大容量数目
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;//
protected transient int modCount = 0;
ArrayList的构造方法
public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}public ArrayList(int initialCapacity) {if (initialCapacity > 0) {this.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {this.elementData = EMPTY_ELEMENTDATA;} else {throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);}
}
ArrayList的主要方法
存:
boolean add(E e);
public boolean add(E e) {//根据当前下角标size+1和当前数组的容量,判断是否需要扩容,如果需要,扩容到1.5倍ensureCapacityInternal(size + 1); // Increments modCount!!//将新元素加入数组中,下角标为size+1elementData[size++] = e;return true;
}private void ensureCapacityInternal(int minCapacity) {if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//如果存储元素的数组为空,容量值为10和minCapacity中的较大者minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);}ensureExplicitCapacity(minCapacity);
}private void ensureExplicitCapacity(int minCapacity) {//更新次数加一modCount++;// overflow-conscious codeif (minCapacity - elementData.length > 0)//如果minCapacity大于当前数组的长度,扩容grow(minCapacity);
}private void grow(int minCapacity) {//将当前数组的长度赋值给oldCapacityint oldCapacity = elementData.length;//新的容量值为原来的1.5倍int newCapacity = oldCapacity + (oldCapacity >> 1);if (newCapacity - minCapacity < 0)//如果新容量值比minCapacity 值小,新容量值即为minCapacitynewCapacity = 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//如果minCapacity小于零,直接抛出OOM异常throw new OutOfMemoryError();//如果minCapacity大于最大数组容量,则返回Integer的最大值,否则返回return (minCapacity > MAX_ARRAY_SIZE) ?Integer.MAX_VALUE :MAX_ARRAY_SIZE;
}
void add(int index,E e);
public void add(int index, E element) {//校验下角标index是否越界rangeCheckForAdd(index);//判断是否需要扩容ensureCapacityInternal(size + 1); // Increments modCount!!//将当前数组中下角标为[index,size]的元素复制到[index+1,size+1]的位置System.arraycopy(elementData, index, elementData, index + 1,size - index);//将element放置到数组下角标为index的位置elementData[index] = element;//数组内元素个数加1size++;
}private void rangeCheckForAdd(int index) {if (index > size || index < 0)//如果index大于数组元素的个数,或者index<0,抛出下角标越界异常throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
E set(int index,E e);
public E set(int index, E element) {//校验下角标是否越界rangeCheck(index);//将数组中下角标为index的元素赋值给oldValueE oldValue = elementData(index);//再将新元素放置到下角标index位置elementData[index] = element;//返回旧值return oldValue;
}
取:
E get(int index);
public E get(int index) {//校验下角标是否越界rangeCheck(index);//返回数组中下角标为index的元素return elementData(index);
}private void rangeCheck(int index) {if (index >= size)throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
移除:
E remove(int index);通过下角标移除。
public E remove(int index) {//判断下角标是否越界rangeCheck(index);//修改次数加一modCount++;//将数组中下角标为index的元素赋值给oldValueE oldValue = elementData(index);//要移动的元素个数int numMoved = size - index - 1;if (numMoved > 0)//如果要移动的元素个数大于0,移动// 将elementData数组index+1位置开始拷贝到elementData从index开始的空间 System.arraycopy(elementData, index+1, elementData, index,numMoved);//最后一个元素设为null,并将size-1elementData[--size] = null; // clear to let GC do its work返回旧值return oldValue;
}
boolean remove(Object o);移除指定元素
public boolean remove(Object o) {if (o == null) {//如果要移除的元素为null//循环遍历数组for (int index = 0; index < size; index++)if (elementData[index] == null) {//如果某个下角标的元素为null//移除该下角标的元素fastRemove(index);return true;}} else {//循环遍历数组for (int index = 0; index < size; index++)if (o.equals(elementData[index])) {//如果某个下角标的元素为o移除该下角标的元素fastRemove(index);return true;}}return false;
}private void fastRemove(int index) {//修改次数加一modCount++;//要移动的元素个数int numMoved = size - index - 1;if (numMoved > 0)// 将elementData数组index+1位置开始拷贝到elementData从index开始的空间 System.arraycopy(elementData, index+1, elementData, index,numMoved);elementData[--size] = null; // clear to let GC do its work
}
转载于:https://my.oschina.net/u/3765527/blog/1828334
Jdk8集合源码解析---ArrayList相关推荐
- 源码 解析_最详细集合源码解析之ArrayList集合源码解析
从今天开始我会将集合源码分析陆陆续续整理,写成文章形成集合源码系列文章,方便大家学习 ArrayList集合源码其实相对比较简单,整个源码结构相对于HashMap等源码要好理解的多:先来看下Array ...
- Java集合系列---List源码解析(ArrayList和LinkedList的区别)
List源码主要讲ArrayList,LinkedList,Vector三个类 1 ArrayList ArrayList是一个底层基于数组的集合, 首先来看一下它的继承关系, public clas ...
- list最大容量_Java 基础(四)集合源码解析 List
List 接口 前面我们学习了Iterator.Collection,为集合的学习打下了基础,现在我们来学习集合的第一大体系 List. List 是一个接口,定义了一组元素是有序的.可重复的集合. ...
- lamda获取参数集合去空_集合源码解析之LinkedList
在日常开发中,最常用的List是ArrayList其次便是LinkedList了.上次我们已经研究过了ArrayList,今天来深入学习下LinkedList... 概述 LinkedList顾名思义 ...
- Java集合源码解析
文章目录 1.集合包 1.1 ArrayList 实现方式 创建:ArrayList() 插入对象:add(E) 删除对象:remove(E) 获取单个对象:get(int) 遍历对象:iterato ...
- JDK8 HashMap源码解析
1.概述 本篇文章我们来聊聊大家日常开发中常用的一个集合类 - HashMap.HashMap 最早出现在 JDK 1.2中,底层基于散列算法实现.HashMap 允许 null 键和 null 值, ...
- JDK8 ThreadLocal 源码解析与最佳实践
文章目录 用法 Example1 Example2 Springboot @Transcation 注解的原理 Entry 的 Key 设置为弱引用有什么好处 内存泄漏问题 This class pr ...
- Java集合源码解析之ArrayList
uml类图: 基本简介: ArrayList的底层数据结构是数组,所以内存需要为arrayList保证有足够的连续的内存空间. 添加操作会导致数组扩容,数组扩容比较消耗性能. 非尾部的添加和删除元素操 ...
- JDK源码解析--ArrayList
一.ArrayList简介 ArrayList是用一个数组实现的集合,支持随机访问,元素有序且可以重复. ArrayList是一种变长的集合类,基于定长数组实现. ArrayList允许空值和重复元素 ...
最新文章
- Error running query: MetaException(message:Got exception: java.net.ConnectException Call From XXXX
- 将来,你会成为这三种程序员之一
- 数据库相关中间件介绍
- WebRTC视频编解码器性能评估
- ubuntu安装VMware出错
- 如何以及何时使用例外
- php 删除上传文件,php实现文件上传、下载和删除的方法
- 图像分类 数据准备(将文件夹中所有图片路径写到TXT文件中)
- java 反射基础_Java基础教程:反射基础
- 《深入学习 Golang》并发编程
- C#GDI绘制自定义字体
- 用Eclipse远程调试部署在Tomcat下的Web应用程序
- Cesium 已知两点,计算以一个点为圆心,将另一个点旋转一定度数后的新点的坐标/position_A绕position_B逆时针旋转angle度(角度)得到新点 function rotatedPo
- 5G+北斗RTK定位:高精度定位技术发展更进一步
- 用批处理共享打印机电脑设置
- 用 TypeScript 写一个轻量级的 UI 框架之八:表单控件之富文本编辑器
- 如何用公式编辑器打半中括号?
- linux 无线网卡ping不同,请教高手,本地网卡和无线网卡均不能ping通网关
- 芯片前沿 | 云端芯片功耗问题日益严重
- AT指令表(中文详解)
热门文章
- python accept解析_python中requests库使用方法详解
- matlab篮球队需要五名队员,MATLAB应用与数学欣赏.doc
- 计算机科学与技术专业综合二,计算机科学与技术专业综合一第二页
- 如何更改jupyter notebook默认存储路径
- 【 Vivado 】输入延迟约束实例
- Verilog: How to avoid 'Redeclaration of ansi port'
- 红帽Linux 6.5上配置ASM流程
- Eclipse中配置Tomcat
- scala之Actors
- LinearLayout、RelativeLayout、FrameLayout居中显示