1.概览

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable

实现了 RandomAccess 接口,因此支持随机访问。这是理所当然的,因为ArrayList 是基于数组实现的。

数组的默认大小为 10。

private static final int DEFAULT_CAPACITY = 10;

2.序列化

ArrayList基于数组实现,并且具有动态扩容特性,因此保存元素的数组不一定都会被使用,那么就没必要全部进行序列化。

保存元素的数组elementData使用transient修饰,该关键字声明数组默认不会被序列化。

transient Object[] elementData; // non-private to simplify nested class access

ArrayList 实现了writeObject() 和 readObject() 来控制只序列化数组中有元素填充那部分内容。

private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {elementData = EMPTY_ELEMENTDATA;// Read in size, and any hidden stuffs.defaultReadObject();// Read in capacitys.readInt(); // ignoredif (size > 0) {// be like clone(), allocate array based upon size not capacityensureCapacityInternal(size);Object[] a = elementData;// Read in all elements in the proper order.for (int i=0; i<size; i++) {a[i] = s.readObject();}}
}
private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException{// Write out element count, and any hidden stuffint expectedModCount = modCount;s.defaultWriteObject();// Write out size as capacity for behavioural compatibility with clone()s.writeInt(size);// Write out all elements in the proper order.for (int i=0; i<size; i++) {s.writeObject(elementData[i]);} if (modCount != expectedModCount) {throw new ConcurrentModificationException();}
}

序列化时需要使用 ObjectOutputStream 的 writeObject() 将对象转换为字节流并输出。

而 writeObject() 方法在传入的对象存在 writeObject() 的时候会去反射调用该对象的 writeObject() 来实现序列化。

反序列化使用的是 ObjectInputStream 的readObject() 方法,原理类似。

ArrayList list = new ArrayList();
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
oos.writeObject(list);

3.扩容

添加元素时使用 ensureCapacityInternal() 方法来保证容量足够,如果不够时,需要使用 grow() 方法进行扩容,新容量的大小为 oldCapacity + (oldCapacity>> 1) ,也就是旧容量的 1.5 倍。

扩容操作需要调用 Arrays.copyOf() 把原数组整个复制到新数组中,这个操作代价很高,因此最好在创建 ArrayList 对象时就指定大概的容量大小,减少扩容操作的次数。

public boolean add(E e) {ensureCapacityInternal(size + 1); // Increments modCount!!elementData[size++] = e;return true;
} private void ensureCapacityInternal(int minCapacity) {if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);}     ensureExplicitCapacity(minCapacity);
} private void ensureExplicitCapacity(int minCapacity) {modCount++;// overflow-conscious codeif (minCapacity - elementData.length > 0)grow(minCapacity);
} private void grow(int minCapacity) {// overflow-conscious codeint oldCapacity = elementData.length;int newCapacity = oldCapacity + (oldCapacity >> 1);if (newCapacity - minCapacity < 0)newCapacity = 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);
}

4.删除元素

需要调用 System.arraycopy() 将 index+1 后面的元素都复制到 index 位置上,该操作的时间复杂度为 O(N),可以看出 ArrayList 删除元素的代价是非常高的。

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;
}

5. Fail-Fast

modCount 用来记录 ArrayList 结构发生变化的次数。

  • 结构发生变化是指添加或者删除至少一个元素的所有操作,或者是调整内部数组的大小,仅仅只是设置元素的值不算结构发生变化。

在进行序列化或者迭代等操作时,需要比较操作前后 modCount 是否改变,如果改变了需要抛出 ConcurrentModificationException。

private void writeObject(java.io.ObjectOutputStream s)throws java.io.IOException{// Write out element count, and any hidden stuffint expectedModCount = modCount;s.defaultWriteObject();// Write out size as capacity for behavioural compatibilitywith clone()s.writeInt(size);// Write out all elements in the proper order.for (int i=0; i<size; i++) {s.writeObject(elementData[i]);} if (modCount != expectedModCount) {throw new ConcurrentModificationException();}
}

ArrayList源码相关推荐

  1. java1.8 indexes_java1.8源码之ArrayList源码解读

    文章目录 一.ArrayList概述1.1 ArrayList简介1.2 ArrayList数据结构 二.ArrayList源码分析2.1 ArrayList继承结构和层次关系2.2 类的属性2.3 ...

  2. JDK12下的ArrayList源码解读 与 Vector的对比

    ArrayList源码阅读. //测试代码实现如下 private static void arrayList() {ArrayList<String> list = new ArrayL ...

  3. java function获取参数_「Java容器」ArrayList源码,大厂面试必问

    ArrayList简介 ArrayList核心源码 ArrayList源码分析 System.arraycopy()和Arrays.copyOf()方法 两者联系与区别 ArrayList核心扩容技术 ...

  4. java list addall源码_Java集合:ArrayList源码分析

    其实我看到已有很多大佬写过此类文章,并且写的也比较清晰明了,那我为何要再写一遍呢?其实也是为了加深本身的印象,巩固本身的基础html (主要是不少文章没有写出来我想知道的东西!!!​!!!!)java ...

  5. Java 集合系列(2): ArrayList源码深入解析和使用示例

    戳上面的蓝字关注我们哦! 精彩内容 精选java等全套视频教程 精选java电子图书 大数据视频教程精选 java项目练习精选 概要 上一章,我们学习了Collection的架构.这一章开始,我们对C ...

  6. 扩容是元素还是数组_02 数组(附ArrayList源码分析)

    定义 用一组连续的内存空间存储一组具有相同类型的数据的线性表数据结构. 优势 支持通过下标快速的随机访问数据,时间复杂度为O(1). 劣势 通常情况下,插入和删除效率低下,每次操作后,需要进行后续元素 ...

  7. 增加数组下标_数组以及ArrayList源码解析

    点击上方"码之初"关注,···选择"设为星标" 与精品技术文章不期而遇 前言 前一篇我们对数据结构有了个整体的概念上的了解,没看过的小伙伴们可以看我的上篇文章: ...

  8. 面试官系统精讲Java源码及大厂真题 - 05 ArrayList 源码解析和设计思路

    05 ArrayList 源码解析和设计思路 耐心和恒心总会得到报酬的. --爱因斯坦 引导语 ArrayList 我们几乎每天都会使用到,但真正面试的时候,发现还是有不少人对源码细节说不清楚,给面试 ...

  9. 顺序线性表 ---- ArrayList 源码解析及实现原理分析

    原创播客,如需转载请注明出处.原文地址:http://www.cnblogs.com/crawl/p/7738888.html ------------------------------------ ...

  10. JDK源码-ArrayList源码

    1,继承结构图:      -1,ArrayList继承AbstractList抽象类,实现List.RandomAccess.Cloneable.Serializable接口.      -2,查看 ...

最新文章

  1. visualVM 安装使用
  2. 零基础入门学习Python (9)-列表(1)
  3. seaborn可视化displot绘制直方图(histogram)并通过axvline函数在直方图中添加均值(mean)竖线(自定义均值竖线色彩)
  4. Java 深、浅克隆
  5. 谷歌开发者大会焦点:大中华区新掌门亮相,Android 10原生支持5G,TF2.0大更新...
  6. 字符串匹配算法(Trie树)
  7. Python_模拟登录(爬取教务系统信息并制作查询界面)
  8. oracle老报604和10275,翻出来了 老东西了 , oracle 数据库解析 extent 数据结构解析...
  9. Bailian2734 十进制到八进制【入门】(POJ NOI0113-45)
  10. 生成随机验证码,上传图片文件,解析HTML
  11. python 数组中取出最小值_每日算法系列【LeetCode 153】寻找旋转排序数组中的最小值...
  12. mysql+sqlplus命令找不到_SQLPLUS命令技巧
  13. access 数据库模糊查询
  14. 宁波保哥后院_如何抛出终极后院电影之夜
  15. 微信机器人 DIY 从 0 到 1
  16. 3dmax说课稿计算机平面设计,3dsmax说课稿.ppt
  17. 计算机语言缩写 dos,dos是什么意思 dos缩写中英全称是什么
  18. ENSP实验——Telnet远程连接
  19. Linux (deepin)网络管理详解
  20. flask---》Marshmallow介绍及基础使用

热门文章

  1. CentOS 7 使用Google-Authenticator进行多因素认证
  2. Java后端,应该日常翻看的中文技术网站
  3. 2016/08/24 CppCon 2015 Bjarne Stroustrup “Writing Good C++14
  4. .net framework 25007 error
  5. 王峰:Hadoop生态技术在阿里全网商品搜索实战
  6. pandas 读csv 报错 UnicodeDecodeError: 'utf-8' codec can't decode byte 0xca in position 0: invalid cont
  7. 一篇文章教你弄懂 SpringMvc中的HandlerInterceptor
  8. linux fedora 35 彻底卸载idea2021.2.2
  9. win10微软账户登录后以管理员都无法修改hosts文件解决办法
  10. linux ffmpeg加速和合并视频命令