Java ArrayList类源码解析
ArrayList是最常用的集合类,底层是由数组实现的
首先可以看到,有两个static final对象数组,也就是被线程间共享的,EMPTY_ELEMENTDATA是非default大小的空集合,原因是要辨别第一次添加元素时应该扩展的大小。
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData;这里是存储实际元素的对象数组,transient关键字表示该部分内容不能被序列化,ArrayList实际上序列化调用的是writeObject和readObject方法,而不是直接由elementData进行序列化,原因是elementData里面有空元素,这部分不需要进行序列化,可以节约内存和时间。
private int size;是实际元素的个数
protected transient int modCount = 0;modCount的作用的保证线程安全,ArrayList本身是非同步的集合类,出现遍历操作都要检查modCount值是否改变。除了自身的set方法外,其他所有存在对elementData写入的操作都会增加modCount值。
public ArrayList(int initialCapacity)给定参数为0时elementData直接赋值为EMPTY_ELEMENTDATA,否则新建一个指定大小的数组
public ArrayList()直接赋值DEFAULTCAPACITY_EMPTY_ELEMENTDATA
public ArrayList(Collection<? extends E> c)若集合c不为空,elementData引用c.toArray产生的数组,若产生的不是Object[]需要再调用Arrays.copyOf进行复制。集合为空则赋值为EMPTY_ELEMENTDATA
public void trimToSize()通过Arrays.copyOf将elementData中的空元素去掉,若size==0则赋值为EMPTY_ELEMENTDATA
public void ensureCapacity(int minCapacity)参数给定所需的最小大小,检查该大小是否大于最小扩展大小(DEFAULTCAPACITY_EMPTY_ELEMENTDATA时该值为10否则为0),大于时调用ensureExplicitCapacity(minCapacity)对集合进行扩展,可以手动调用
private void ensureCapacityInternal(int minCapacity)和上一个相似,add元素时检查大小是否足够,仍未DEFAULTCAPACITY_EMPTY_ELEMENTDATA时扩展10和minCapacity的较大值,否则直接扩展minCapacity
private void ensureExplicitCapacity(int minCapacity) minCapacity大于elementData的元素个数时,调用grow(minCapacity),无论是否增长了大小,该方法都会增加modCount
private void grow(int minCapacity)增长大小为minCapacity和elementData.length*1.5中的较大值,最大不能超过Integer.max(2的31次)-8,通过Arrays.copyOf复制元素
public int size()返回size值
public boolean isEmpty()返回size是否为0
public int indexOf(Object o)o为null时检查elementData中是否有元素==o,否则检查是否有o.equals(x),存在则返回第一个符合的下标,不存在返回-1
public int lastIndexOf(Object o)与上一个方法相比区别在于从尾部开始遍历,返回的是下标最大的一个
public boolean contains(Object o)调用indexOf,返回不为-1时为true
public Object clone()新建一个ArrayList,elementData复制过去,其他内部变量也相同
public Object[] toArray()返回Arrays.copyOf(elementData, size),所以不含后面的空数组
public <T> T[] toArray(T[] a)若a.length<size,则新建一个包含elementData中实际对象的数组返回。否则将elementData中的元素复制给a并设a[size] = null,返回a
public E get(int index)获取指定下标元素内容
public E set(int index, E element)将指定下标元素改为element并返回旧值
public boolean add(E e)检查数组大小是否需要扩展后,添加元素,增加size,一定会增加modCount
public void add(int index, E element)先检查index是否符合范围,然后检查数组大小是否需要扩展,将index后的元素向后复制以为,然后elementData[index]=element,一定会增加modCount
public E remove(int index) 先检查index是否符合范围,然后modCount增加,index后的元素往前复制一位,elementData[size]的值为null便于触发gc,size减一,返回旧元素的值
public boolean remove(Object o)首先按照indexOf的逻辑寻找第一个相等的元素,如果存在则将后面的元素往复制一位最后一个元素设为null并增加modCount返回true,否则返回false。因为index肯定是符合返回的,所以调用不检查index是否符合范围private void fastRemove(int index)
public void clear()modCount增加,将size个元素都设为null,size改为0
public boolean addAll(Collection<? extends E> c)通过System.arraycopy将c的元素复制到集合的后面,modCount增加,size增加c的元素个数,若新size不为0则返回true
public boolean addAll(int index, Collection<? extends E> c)和上面相比区别在于要将c复制到从index开始的位置而不是末尾,同样会增加modCount
protected void removeRange(int fromIndex, int toIndex)增加modCount,将toIndex后面的元素复制到fromIndex开始的位置,多余的设为null便于触发GC,修改size值
public boolean removeAll(Collection<?> c)移除和c中相同的元素,若原本集合中元素个数变动增加modCount
public boolean retainAll(Collection<?> c)保留和c中相同的元素,若原本集合中元素个数变动增加modCount
private void writeObject(java.io.ObjectOutputStream s) 序列化函数,通过s.writeObject将对象写入到输出流中,通过检查modCount的值是否改变来确保线程安全
private void readObject(java.io.ObjectInputStream s)序列化函数,通过s.readObject()将输入流中的对象读取到elementData中
public Iterator<E> iterator()返回一个实现的迭代器,只能从头向尾移动,移动时元素个数不能被其他线程改变。可以移除和forEachRemaining (Consumer<? super E> consumer)进行批量操作,批量操作时modCount不能被其他线程改变
public ListIterator<E> listIterator(int index)返回一个从指定下标开始的列表迭代器是Iterator<E>的继承类,若不输入参数默认从0开始。可以前后移动,移动时检查元素个数不能被其他线程修改。额外提供了set和add方法。
public List<E> subList(int fromIndex, int toIndex)返回一个子集合,对子集合的add remove set操作会改变parent对应的元素,并改变两者的modCount值。subList为抽象类,本身并没有elementData区域,对他元素的操作会直接操作在parent的elementData上
public boolean removeIf(Predicate<? super E> filter)根据过滤器filter移除符合的元素,整个过程要求modCount不能被其他线程改变,先用一个BitSet存储要删除的序号,然后通过removeSet.nextClearBit(i)进行复制移动,最后modCount++
public void replaceAll(UnaryOperator<E> operator)根据规则替换所有符合的元素,会改变modCount
public void sort(Comparator<? super E> c)排序,会改变modCount
个人GitHub地址: https://github.com/GrayWind33
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Java 目录和文件的复制
1.复制一个目录及其子目录、文件到另外一个目录 //复制一个目录及其子目录、文件到另外一个目录 public void copyFolder(File src, File dest) throws IOException { if (src.isDirectory()) { if (!dest.exists()) { dest.mkdir(); } String files[] = src.list(); for (String file : files) { File srcFile = new File(src, file); File destFile = new File(dest, file); // 递归复制 copyFolder(srcFile, destFile); } } else { InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dest); byte[] buffer = new byte[1024]; i...
- 下一篇
Java 概述
Java概述 1.1、什么是Java 1.1.1含义 Java是一种可以撰写跨平台应用软件的面向对象的程序设计语言。Java 技术具有卓越的通用性、高效性、平台移植性和安全性,广泛应用于PC、数据中心、游戏控制台、科学超级计算机、移动电话和互联网,同时拥有全球最大的开发者专业社群。 1.1.2背景 Java是由Sun Microsystems公司推出的Java面向对象程序设计语言(以下简称Java语言)和Java平台的总称。 Java由James Gosling和同事们共同研发,并在1995年正式推出。Java最初被称为Oak,是1991年为消费类电子产品的嵌入式芯片而设计的。1995年更名为Java,并重新设计用于开发Internet应用程序。用Java实现的HotJava浏览器(支持Java applet)显示了Java的魅力:跨平台、动态Web、Internet计算。从此,Java被广泛接受并推动了Web的迅速发展,常用的浏览器均支持Javaapplet。另一方面,Java技术也不断更新。Java自面世后就非常流行,发展迅速,对C++语言形成有力冲击。在全球云计算和移动互联网的产...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS7,8上快速安装Gitea,搭建Git服务器
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS关闭SELinux安全模块
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- SpringBoot2整合Redis,开启缓存,提高访问速度
- CentOS7设置SWAP分区,小内存服务器的救世主