ArrayList源码学习
可增长数组结构
实现:
1. 内部采用数组的方式。
1.1 添加元素,会每次校验容量是否满足, 扩容规则是当前数组长度+当前数组长度的二分之一。容量上限是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,支持添加重复数据
modCount作用:
https://www.cnblogs.com/zuochengsi-9/p/7050351.html
源码分析
package xin.rtime.collections.list;import java.util.Arrays; import java.util.ConcurrentModificationException; import java.util.Iterator; import java.util.NoSuchElementException;// 模拟ArrayList的实现 public class ArrayList<E> {private transient int modCount = 0; // 修改次数private transient Object[] elementData; // 数据集合private static final Object[] EMPTY_ELEMENTDATA = {}; // 默认空数组private int size; // 数组实际个数private static final int DEFAULT_CAPACITY = 10; // 默认长度private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; // 数组最大长度// 默认构造函数public ArrayList() {elementData = EMPTY_ELEMENTDATA; // 默认等于空集合 }// 初始化指定长度public ArrayList(int initialCapacity) {if (initialCapacity < 0) // 长度小于0 抛异常throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);this.elementData = new Object[initialCapacity]; // new一个指定长度的对象数组 }// 添加元素public boolean add(E e) {ensureCapacityInternal(size + 1);elementData[size++] = e; // 放置添加的元素return true;}// 删除元素public boolean remove(E e) {if (e == 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 (e.equals(elementData[index])) { // eqals比较 fastRemove(index);return true;}}return false;}private void fastRemove(int index) {modCount++;int numMoved = size - index - 1; // 当前size - index - 1 数组从0开始if (numMoved > 0)System.arraycopy(elementData, index+1, elementData, index,numMoved); // system arraycopyelementData[--size] = null; // clear to let GC do its work gc回收 }public E remove(int index) {rangeCheck(index);modCount++;E oldValue = elementData(index);int numMoved = size - index - 1;if (numMoved > 0)System.arraycopy(elementData, index+1, elementData, index,numMoved);elementData[--size] = null; // clear to let GC do its workreturn oldValue;}// 获取元素public E get(int index) {rangeCheck(index); // index校验return elementData(index);}@SuppressWarnings("unchecked")E elementData(int index) {return (E) elementData[index];}private void rangeCheck(int index) {if (index >= size)throw new IndexOutOfBoundsException(outOfBoundsMsg(index));}private String outOfBoundsMsg(int index) {return "Index: "+index+", Size: "+size;}// 返回元素个数public int size() {return size;}// 判断当前容量是否能否装下元素private void ensureCapacityInternal(int minCapacity) {if (elementData == EMPTY_ELEMENTDATA) // 空集合minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); // 10 传入的 ensureExplicitCapacity(minCapacity);}// 提供外部遍历public Iterator<E> iterator() {return new Itr();}private class Itr implements Iterator<E> {int cursor; // index of next element to return 游标int lastRet = -1; // index of last element returned; -1 if no such 最后元素下标int expectedModCount = modCount; // 当前数组修改次数public boolean hasNext() {return cursor != size; // 当前游标是否等于size }@SuppressWarnings("unchecked")public E next() {checkForComodification(); // 检查数组是否被操作过int i = cursor;if (i >= size)throw new NoSuchElementException();Object[] elementData = ArrayList.this.elementData;if (i >= elementData.length)throw new ConcurrentModificationException();cursor = i + 1;return (E) elementData[lastRet = i];}public void remove() {if (lastRet < 0)throw new IllegalStateException();checkForComodification(); // 检查集合是否被操作过try {ArrayList.this.remove(lastRet);cursor = lastRet;lastRet = -1;expectedModCount = modCount;} catch (IndexOutOfBoundsException ex) {throw new ConcurrentModificationException();}}final void checkForComodification() {if (modCount != expectedModCount)throw new ConcurrentModificationException();}}// 判断容量 扩容private void ensureExplicitCapacity(int minCapacity) {modCount++; // 修改+1if (minCapacity - elementData.length > 0) // 当前长度 大于 数组长度 grow(minCapacity);}public void add(int index, E element) {rangeCheckForAdd(index);ensureCapacityInternal(size + 1); // Increments modCount!!System.arraycopy(elementData, index, elementData, index + 1,size - index);elementData[index] = element;size++;}private void rangeCheckForAdd(int index) {if (index > size || index < 0) // index 超出 size 或者 index 小于0 ---> 数组越界throw new IndexOutOfBoundsException(outOfBoundsMsg(index));}public E set(int index, E element) {rangeCheck(index); // 校验index是否满足 E oldValue = elementData(index);elementData[index] = element;return oldValue;}/**<< : 左移运算符,num << 1,相当于num乘以2>> : 右移运算符,num >> 1,相当于num除以2>>> : 无符号右移,忽略符号位,空位都以0补齐*/// 扩容private void grow(int minCapacity) {int oldCapacity = elementData.length; // 当前数组长度int newCapacity = oldCapacity + (oldCapacity >> 1); // 新容量大小 = 原来长度 + 原来长度 右移一位,除以2if (newCapacity - minCapacity < 0) // 新长度 - 传的长度 小于 0newCapacity = minCapacity; // if (newCapacity - MAX_ARRAY_SIZE > 0) // 当前长度超出最大容量newCapacity = hugeCapacity(minCapacity);// minCapacity is usually close to size, so this is a win:elementData = Arrays.copyOf(elementData, newCapacity); // 拷贝原来数据 }// 判断容量private int hugeCapacity(int minCapacity) {if (minCapacity < 0) // overflowthrow new OutOfMemoryError();return (minCapacity > MAX_ARRAY_SIZE) ?Integer.MAX_VALUE :MAX_ARRAY_SIZE;}}
转载于:https://www.cnblogs.com/LuisYang/p/10034514.html
ArrayList源码学习相关推荐
- 集合框架-ArrayList源码学习
MIT麻省理工学院讲义上的一段话: 如果没有完全理解 JAVA 库中的具有决定性的部分,你就不可能成为一个优秀的 JAVA 程序员.基本类型都包含在 java.lang 中.java.util包提供了 ...
- ArrayList源码学习第二天全解
目录 1,删除元素 1.1,删除单个元素remove 1.2, 移除多个元素removeRange 1.3,移除在 c 中的元素batchRemove 4,移除不在 c 中的元素retainAll 2 ...
- JDK源码学习之Arraylist与LinkedList
ArrayList和LinkedList是我们在开发过程中常用的两种集合类,本文将从底层源码实现对其进行简单介绍. 下图是Java集合类所涉及的类图. 一.ArrayList 从上面的集合类图可以看出 ...
- Java 集合系列(2): ArrayList源码深入解析和使用示例
戳上面的蓝字关注我们哦! 精彩内容 精选java等全套视频教程 精选java电子图书 大数据视频教程精选 java项目练习精选 概要 上一章,我们学习了Collection的架构.这一章开始,我们对C ...
- 增加数组下标_数组以及ArrayList源码解析
点击上方"码之初"关注,···选择"设为星标" 与精品技术文章不期而遇 前言 前一篇我们对数据结构有了个整体的概念上的了解,没看过的小伙伴们可以看我的上篇文章: ...
- 面试官系统精讲Java源码及大厂真题 - 05 ArrayList 源码解析和设计思路
05 ArrayList 源码解析和设计思路 耐心和恒心总会得到报酬的. --爱因斯坦 引导语 ArrayList 我们几乎每天都会使用到,但真正面试的时候,发现还是有不少人对源码细节说不清楚,给面试 ...
- JAVA小项目实例源码—学习娱乐小助手
代码地址如下: http://www.demodashi.com/demo/11456.html 一.程序实现 项目目录: MyJFrame:实现项目界面样式: AppProcess:实现调用api或 ...
- 顺序线性表 ---- ArrayList 源码解析及实现原理分析
原创播客,如需转载请注明出处.原文地址:http://www.cnblogs.com/crawl/p/7738888.html ------------------------------------ ...
- JDK源码-ArrayList源码
1,继承结构图: -1,ArrayList继承AbstractList抽象类,实现List.RandomAccess.Cloneable.Serializable接口. -2,查看 ...
最新文章
- 决策树算法详解(2)
- matlab积分与绘图
- oracle 中关于null的操作
- 5-29 vscode占位
- eclipse maven创建web项目
- 嘉实多RO150合成齿轮油
- mysql 3种报错_MySQL读取Binlog日志常见的3种错误-阿里云开发者社区
- php copy 文件夹,php删除与复制文件夹及其文件夹下所有文件的实现代码
- 一步步学习javascript基础篇(8):细说事件
- 颜宁谈院士增选:导师施一公让我特别受益的是:纯粹,做事情的纯粹
- python 读取 Excel 文件的方法 csv.reader
- Android网络类型判断(2g、3g、wifi)
- C运行时库(CRT)
- 算法求100以内的质数
- excel查找窗口被拉边上_excel
- 幼儿园调查过程怎么写_幼儿园家长的调查问卷话术
- 【日语】日文假名输入与键盘对应
- 【Linux】如何将ntfs硬盘挂载到home目录下并具有读写权限
- SQL 函数 —— TRUNCATE详解示例
- 非会员免费建立QQ群的方法!