目录

  • ArrayList简介:
  • ArrayList 相关方法介绍
    • 代码表示
    • 相关方法源码分析

ArrayList简介:

java.util.ArrayList 是我们最常用的一个类,ArrayList 底层是动态数组,读者可以把它理解为数组的实现

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

如上代码我们可以看到 ArrayList 继承了 AbstractList() 抽象类,并实现了 List, RandomAccess, Cloneable, Serializable 接口

AbstractList :

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {}

可以看到AbstractList 继承了 AbstractCollection 接口, 并实现了List 接口

AbstractCollection :

public abstract class AbstractCollection<E> implements Collection<E> {}

AbstractCollection 是一个抽象类,实现了Collection 接口,并提供了某些方法的具体实现。

Collection:

Collection 是一个顶级接口,是很多集合类的顶级接口,继承了Iterable ,支持轻量级遍历其中元素

public interface Collection<E> extends Iterable<E> {}

List :

ArrayList 实现了List接口,List 也是一个和Collection 媲美的顶级接口,继承了Collection 接口

public interface List<E> extends Collection<E> {}

它是许多集合类的父类,

eg:

List list = new ArrayList();
List list2 = new LinkedList();

RandomAccess

RandomAccess 也是一个顶级接口,实现了此接口的类支持随机访问

Cloneable

Cloneable 接口是一个顶级接口,实现了此接口的类支持浅拷贝

Serializable

实现此接口的类支持序列化的功能

类之间的继承关系如图

ArrayList 相关方法介绍

trimToSize()

代码表示

实践才是检验真理最好的方式:

import java.util.*;/*** 详述ArrayList 基本用法*/
public class ArrayListTest {private static class SortList implements Comparator<String> {@Overridepublic int compare(String o1, String o2) {Integer i1 = Integer.valueOf(o1);Integer i2 = Integer.valueOf(o2);if(i1 < i2){return -1;}else if(i1 == i2){return 0;}return 1;}}// 使用可变参数,能够接受任意个参数public Set<String> putSet(String...args){Set<String> sets = new HashSet<>();for(String str : args){sets.add(str);}return sets;}public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();list.add("111");list.add("222");// 在指定位置添加元素list.add(0,"333");System.out.println(list);// 进行外部排序list.sort(new SortList());System.out.println(list);list.clear();System.out.println(list.size());// 使用addAll添加元素ArrayListTest at = new ArrayListTest();list.addAll(at.putSet("1","2","3"));Iterator<String> it = list.iterator();while(it.hasNext()){System.out.println(it.next());// 移除所有元素it.remove();}System.out.println("list是否为空 ? " + list.isEmpty());list.add("111");// 在指定位置添加一个set集合list.addAll(0,at.putSet("1","2","3"));System.out.println(list);// 是否包含指定元素if(list.contains("111")) {list.remove("111");}System.out.println(list);System.out.println(list.indexOf("1"));// 注意subList()这个方法是左开右闭区间,Java 中很多都是类似的System.out.println(list.subList(0,3));// 扩大list的容量list.ensureCapacity(10);// 去掉list空闲的容量list.trimToSize();// 获取某个特定的元素System.out.println(list.get(1));// 创建一个list的双向链表ListIterator<String> listIterator = list.listIterator();while(listIterator.hasNext()){// 移到list的末端System.out.println(listIterator.next());}System.out.println("--------------------------");while (listIterator.hasPrevious()){// 移到list的首端System.out.println(listIterator.previous());}// 把list转换为数组Object[] objects = list.toArray();System.out.println("objects = " + objects);}
}

相关方法源码分析

源码的具体分析是根据上面的代码示例得出,因为只看源码好像并不能看懂什么,需要根据具体的代码一步一步debug 进行跟踪

add()方法

解释:添加指定的元素在list的末尾

    /*** 添加指定的元素在list的末尾*/// 假设第一次添加的是 "111"public boolean add(E e) {// size是0,所以size + 1 传的是1ensureCapacityInternal(size + 1); // elementData[0] = 111 , size++ = 1elementData[size++] = e;return true;}// 此方法用来进行list 扩容private void ensureCapacityInternal(int minCapacity) {// 此时elementData 并没有存储元素,为0if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {// 则minCapacity 取默认初始容量和minCapacity 的最大值 (取1 和 10的最大值)minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);}// 确保清晰的容量(最小容量与List元素的比较)ensureExplicitCapacity(minCapacity);}// 在list中添加了一个元素,所以会导致结构化的修改,"结构化的修改"见下面解释// 此时minCapacity 为 10private void ensureExplicitCapacity(int minCapacity) {// 次数 + 1 // 这个列表被修改结构的次数(比如添加和删除元素)会用modCount表示. 结构化修改是指的是能够// 改变列表容量的操作,或者其他方式改变它,导致遍历的过程会产生错误的结果。modCount++;// overflow-conscious code// 10 - 0 > 0 走grow 方法if (minCapacity - elementData.length > 0)grow(minCapacity);}/*** 增加容量确保容纳足够的元素* * 参数传过来的是10*/private void grow(int minCapacity) {// overflow-conscious code// oldCapacity = 0int oldCapacity = elementData.length;// newCapacity = 0int newCapacity = oldCapacity + (oldCapacity >> 1);// newCapacity - minCapacity = -10if (newCapacity - minCapacity < 0)// newCapacity = 10newCapacity = minCapacity;// MAX_ARRAY_SIZE = 数组分配的最大空间 = 2147483639// 一般情况下不会比 MAX_ARRAY_SIZE 还要大if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);// minCapacity is usually close to size, so this is a win:// 底层还是用的System.arraycopy(), 关于System.arrayCopy() 读者可以参考我的另一篇博客elementData = Arrays.copyOf(elementData, newCapacity);}

相关常用的基本数据类型包装类的值: Java基本数据类型包装类常用的值

add(int index, E element)

解释:在list中指定位置插入指定的元素,如果当前位置有元素,就移动当前位置的元素

    /*** 在list中指定位置插入指定的元素,如果当前位置有元素,就移动当前位置的元素* 要插入的位置的后面所有元素的位置向前 + 1**/public void add(int index, E element) {// 检查 0 这个位置是否越界rangeCheckForAdd(index);// 不再赘述,读者可以自行debugensureCapacityInternal(size + 1);  // Increments modCount!!// 因为从当前位置插入元素,所以当前位置及后面的元素都会向后移动// 使用System.arraycopy 进行数组复制System.arraycopy(elementData, index, elementData, index + 1,size - index);// 为当前元素赋值elementData[index] = element;size++;}/*** 为add 和 addall 提供的范围检查, 不符合条件,抛出IndexOutOfBoundsException 异常*/private void rangeCheckForAdd(int index) {if (index > size || index < 0)throw new IndexOutOfBoundsException(outOfBoundsMsg(index));}

Clear()

解释:移除列表中的所有元素

    /*** 移除list列表中所有的元素,列表会变为空列表在调用此方法后**/public void clear() {// 修改次数 + 1modCount++;// clear to let GC do its work// 把每个变量置空,GC进行回收for (int i = 0; i < size; i++)elementData[i] = null;// 列表的长度变为0size = 0;}

这个方法的源码理解起来还是比较简单的

addAll(Collection<? extends E> c)

解释: 把一个Collection集合添加到list末尾

    /*** 把一个Collection集合(实现了此接口的类)添加到list的末尾,按着迭代的顺序返回。* 此操作的行为是如果在此方法调用的过程中修改了Collection(实现了此接口的类)的话,* 那么这个操作不会成功*/public boolean addAll(Collection<? extends E> c) {// 把Collection 转换为 Object[] 数组Object[] a = c.toArray();// 数组中有三个元素int numNew = a.length;// 因为上面的操作调用了一次list.clear()方法,所以list.size = 0ensureCapacityInternal(size + numNew);  // Increments modCount// 一句话解释: 把a 数组中0个位置的元素 复制到 elementData数组中 第size个位置的元素,// 复制的长度为 numNewSystem.arraycopy(a, 0, elementData, size, numNew);size += numNew;return numNew != 0;}// toArray()方法: /*** 返回一个数组,包含了所有的元素(从第一个元素到最后一个元素)* 返回的数组是很"安全的"因为列表没有引用可以维持(换句话说,这个方法必须分配一个新数组)* 调用者因此可以任意修改返回的数组* 这个方法是数组 和 集合之间的桥梁*/public Object[] toArray() {return Arrays.copyOf(elementData, size);}

iterator(), hasNext(), next()

解释:Iterator方法用于遍历list中的元素,返回一个Itr 的内部类,hasNext()方法用于判断list 中是否还有未遍历的元素,next()方法用于获取下一个元素

    /*** 以适当的顺序返回此列表中元素的迭代器* 返回的iterator 支持fail-fast 机制*/public Iterator<E> iterator() {return new Itr();}/*** Itr 是一个内部类,实现了Iterator接口,可支持快速遍历*/private class Itr implements Iterator<E> {// 下一个元素返回的下标int cursor;       // index of next element to return// 最后一个元素返回的下标, 如果没有返回-1int lastRet = -1; // index of last element returned; -1 if no such// expectedModCount 期望的修改次数,默认是和modCount(修改次数相同,用于iterator判断fail-fast机制)int expectedModCount = modCount;public boolean hasNext() {return cursor != size;}@SuppressWarnings("unchecked")public E next() {// 判断遍历的过程中是否触发fail-fast机制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() {// 如果lastRet < 0,说明 lastRet 没有被改变,// 所以应该是没有调用next()就调用了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();}}@Override@SuppressWarnings("unchecked")public void forEachRemaining(Consumer<? super E> consumer) {Objects.requireNonNull(consumer);final int size = ArrayList.this.size;int i = cursor;if (i >= size) {return;}final Object[] elementData = ArrayList.this.elementData;if (i >= elementData.length) {throw new ConcurrentModificationException();}while (i != size && modCount == expectedModCount) {consumer.accept((E) elementData[i++]);}cursor = i;lastRet = i - 1;checkForComodification();}// 如果修改次数不满足预期修改次数的话,抛出异常final void checkForComodification() {if (modCount != expectedModCount)throw new ConcurrentModificationException();}}

addAll(int index,Collection<? extends E> c)

解释:在某个位置添加Collection集合

    /*** 在指定的位置下标插入一个Collection集合*/public boolean addAll(int index, Collection<? extends E> c) {rangeCheckForAdd(index);Object[] a = c.toArray();int numNew = a.length;ensureCapacityInternal(size + numNew);  // Increments modCount// 需要移动的元素个数int numMoved = size - index;if (numMoved > 0)// 第一次数组复制,从elementData中的index位置开始,复制到index + numNew位置上,复制numMoved个元素System.arraycopy(elementData, index, elementData, index + numNew,numMoved);// 第二次数组复制,从a 数组中的第0个位置开始,复制到elementData第index位置上你,复制numNew个元素System.arraycopy(a, 0, elementData, index, numNew);size += numNew;return numNew != 0;}

contains(Object o)

解释:判断list列表是否包含某个元素

    /*** 返回true,如果这个列表包含指定的元素* 更进一步来说,当且仅当list包含至少一个元素的情况下,返回true*/public boolean contains(Object o) {return indexOf(o) >= 0;}/*** 返回列表中第一次出现指定元素的下标值,如果不包含指定元素,则返回-1。* 更进一步来说,返回最小的索引当(o == null ? get(i) == null : o.equals(get(i)))的时候* 或者返回-1 没有此下标值**/public int indexOf(Object o) {// 如果o这个对象等于null,就判断elementData中是否有空元素,如果有,返回if (o == null) {for (int i = 0; i < size; i++)if (elementData[i]==null)return i;} else {// 如果不为null,返回这个值的存储位置for (int i = 0; i < size; i++)if (o.equals(elementData[i]))return i;}return -1;}

remove(Object o)

解释:移除list中的某个元素

    /*** 如果存在,则移除list中某个第一次出现的元素。如果这个list不包含指定元素,就不会改变**/public boolean remove(Object o) {if (o == null) {for (int index = 0; index < size; index++)if (elementData[index] == null) {//快速移除某个指定元素fastRemove(index);return true;}} else {for (int index = 0; index < size; index++)if (o.equals(elementData[index])) {fastRemove(index);return true;}}return false;}/** 私有的移除方法,并且不返回被移除的元素,这个源码比较简单*/private void fastRemove(int index) {modCount++;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 work}

indexOf(Object o)

解释:检索某个元素的位置

此源码和contains(Object o)中调用的indexOf 源码相同

subList(int fromIndex, int toIndex)

解释:返回list列表的一个片段

    /*** 返回list列表中的一部分视图(相当于list片段),[fromIndex,toIndex),如果fromIndex 和* toIndex 相同的话,表明这个list为空,这个返回的list被返回,所以在list中并没有结构的改变* 这个返回的list片段支持所有的list操作*/public List<E> subList(int fromIndex, int toIndex) {// subList 范围检查subListRangeCheck(fromIndex, toIndex, size);return new SubList(this, 0, fromIndex, toIndex);}static void subListRangeCheck(int fromIndex, int toIndex, int size) {if (fromIndex < 0)throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);if (toIndex > size)throw new IndexOutOfBoundsException("toIndex = " + toIndex);if (fromIndex > toIndex)throw new IllegalArgumentException("fromIndex(" + fromIndex +") > toIndex(" + toIndex + ")");}private class SubList extends AbstractList<E> implements RandomAccess {private final AbstractList<E> parent;private final int parentOffset;private final int offset;int size;SubList(AbstractList<E> parent,int offset, int fromIndex, int toIndex) {this.parent = parent;this.parentOffset = fromIndex;this.offset = offset + fromIndex;this.size = toIndex - fromIndex;this.modCount = ArrayList.this.modCount;}}

ensureCapacity(int minCapacity)

解释:扩大list的容量

    /*** 增加ArrayList实例的容量,如果必须的话,确保它能持有最小容量的元素*/public void ensureCapacity(int minCapacity) {int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)// any size if not default element table? 0// larger than default for default empty table. It's already// supposed to be at default size.: DEFAULT_CAPACITY;if (minCapacity > minExpand) {ensureExplicitCapacity(minCapacity);}}

trimToSize()

解释:去掉list空闲的容量

    /*** 去掉ArrayList中的多余空间*/public void trimToSize() {modCount++;if (size < elementData.length) {elementData = (size == 0)? EMPTY_ELEMENTDATA: Arrays.copyOf(elementData, size);}}

sort(Comparator<? super E> c)

sort 方法接收一个自定义比较器进行自定义比较,下面来看具体的源码

        @Override@SuppressWarnings("unchecked")public void sort(Comparator<? super E> c) {// 根据上面代码分析,此时modCounnt 已经被修改过三次(添加了三个元素)final int expectedModCount = modCount;// 数组外部排序Arrays.sort((E[]) elementData, 0, size, c);if (modCount != expectedModCount) {throw new ConcurrentModificationException();}modCount++;}

转载于:https://www.cnblogs.com/cxuanBlog/p/10949552.html

ArrayList相关方法介绍及源码分析相关推荐

  1. Stable Diffusion 原理介绍与源码分析(一)

    Stable Diffusion 原理介绍与源码分析(一) 文章目录 Stable Diffusion 原理介绍与源码分析(一) 前言(与正文无关,可以忽略) 总览 说明 Stable Diffusi ...

  2. GAT 算法原理介绍与源码分析

    GAT 算法原理介绍与源码分析 文章目录 GAT 算法原理介绍与源码分析 零. 前言 (与正文无关, 请忽略) 广而告之 一. 文章信息 二. 核心观点 三. 核心观点解读 四. 源码分析 4.1 G ...

  3. ThreadLocal介绍以及源码分析

    ThreadLocal 线程主变量 前面部分引用其他优秀博客,后面源码自己分析的,如有冒犯请私聊我. 用Java语言开发的同学对 ThreadLocal 应该都不会陌生,这个类的使用场景很多,特别是在 ...

  4. Spring_AOP架构介绍与源码分析(含事务深度分析)

    请见链接:http://edu.51cto.com/course/16573.html?source=so 第1章课程介绍6分钟1节 1-1课程介绍[免费试看]06:11 第2章AOP深入分析52分钟 ...

  5. Redis 的 Sentinel哨兵介绍与源码分析(1):初始化部分

    http://www.redis.cn/topics/sentinel.html redis-6.0.8 本文是在官方中文文档的基础上进行的源码分析,其中包含完整的原文,并在此基础上,添加源码介绍. ...

  6. seastar介绍及源码分析

    目录 1.seastar介绍 1.1.机制简介 1.2.使用方法简介 1.2.1 app_template::run 1.2.2 future promise continuation 2.源码分析 ...

  7. SDIO_WiFi驱动学习之SDIO架构介绍及源码分析

    一.引言 因为WiFi驱动比较复杂,所以WiFi驱动的博客将多分几篇来写. 本篇博客主要介绍Linux下的SDIO架构及源码分析. 本文部分内容摘抄自网络,若有侵权,请联系删除. 二.SDIO WiF ...

  8. python Django之 DRF(一)框架介绍、源码分析

    文章目录 一.django rest framework 框架的介绍 1.什么是RESTful规范? 2.RESTful API的介绍 二.drf框架源码解读 1.drf框架的使用 2.APIView ...

  9. python logistic回归_logistic回归介绍与源码分析

    1. 介绍(由线性模型引出logistic回归) 首先介绍一下什么是线性模型呢? 线性模型的定义如下:给定 个属性描述的样本 , 代表样本在第 个属性上的取值. 线性模型的目的是学习一个函数,它可以通 ...

最新文章

  1. 遍历替换字符串中特定字符
  2. java-容器-ArrayList
  3. MSMQ: C# MSMQ编程问题
  4. 解决服务器上安装不了centos7.4的问题
  5. 工业用微型计算机笔记(4)~编码,寄存器,引脚
  6. (转)WindowsPhone基础琐碎总结-----数据绑定(一)
  7. 信息奥赛一本通(1112:最大值和最小值的差)
  8. https的ssl证书申请及服务器的nginx的配置教程
  9. stm32c语言long型数据多少位,stm32 C语言的数据类型说明
  10. php用jquery-ajax上传多张图片限制图片大小
  11. Java网络编程第一章
  12. 【Unreal Engine探索实践】第一个ARPG游戏的探索实践——ACT类第三人称3D动作游戏的简单实现
  13. golang+vue3+websocket 实时推送首页数据或者站内信
  14. 华为:将在员工绩效考核中增加“伙伴满意度”选项;谷歌研究员“走火入魔”,被罚带薪休假;魅族回应被吉利收购 | EA周报...
  15. 百度网盘Linux版本能用吗,百度网盘Linux版使用体验效果
  16. 动车报销凭证怎么取?高铁票的报销凭证在哪里取?
  17. 蓝桥杯-算法训练 印章
  18. WPF Commanding Overview 的笔记
  19. proteus中仿真arduino利用74hc373实现抢答器
  20. ubuntu更改更新源

热门文章

  1. Golang Hash MD4
  2. 【Ajax技术】JQuery的应用与高级调试技巧
  3. ISE与Notepad++关联
  4. Verilog实现交通灯(数电课设)----------旧
  5. arcgis导入坐标点转面_arcgis矢量化建筑数据
  6. 员工管理的html页面,员工管理.html
  7. bom更改编号 sap_【BOM精讲】BOM 入门基本常识
  8. 对象当前正在其他地方使用_2019 为什么我们还会继续使用 PHP ?
  9. CentOS 7笔记yum install epel-release
  10. golang中获取公网ip、查看内网ip、检测ip类型、校验ip区间、ip地址string和int转换、根据ip判断地区国家运营商等