ArrayList 概述 与源码简析

1 ArrayList 创建
ArrayList<String> list = new ArrayList<>();
//构造一个初始容量为10 的空列表
  • 源码分析 当我们使用上面的构造来创建ArrayList的时候,其实其实内部是创建了一个 Object[] 空的数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}
2 ArrayList 添加数据

添加单个数据

    //添加数据arrayList.add("afd");arrayList.add("afd");arrayList.add("afd");System.out.println(arrayList);//[afd, afd, afd]/*** 向ArrayList中的0号位置上 添数据 * 通过这个方法添加数据,位置限定在  0 到 arraylist.size()中*/arrayList.add(0,"qq");System.out.println(arrayList);//[qq, afd, afd, afd]
  • arrayList.add(0,”qq”);

    • 源码中 首先调用了 rangeCheckForAdd(index);方法来检察 传入的角标的范围,不在范围内就抛出异常
    • 而最终是通过 Arrays.copyOf(elementData, newCapacity)这个方法将原来集合中的内容copy到新的集合中去
    //add方法的源码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)throw new IndexOutOfBoundsException(outOfBoundsMsg(index));}

添加集合中的数据

ArrayList<Integer> arrayList2 = new ArrayList<Integer>();arrayList2.add(1);ArrayList<Integer> arrayList3 = new ArrayList<Integer>();arrayList3.add(3);//将 arraylist2 中的数据全部添加到arraylist3集合中arrayList3.addAll(arrayList2);System.out.println(arrayList3);//[3, 1]
  • 分析其源码我们会发现,其先是通过 toArray()方法将集合数据转为数组数据, 最终是通过 System.arraycopy()方法 数据copy到了一个新的数组中
public boolean addAll(Collection<? extends E> c) {Object[] a = c.toArray();int numNew = a.length;ensureCapacityInternal(size + numNew);  // Increments modCountSystem.arraycopy(a, 0, elementData, size, numNew);size += numNew;return numNew != 0;}
3 ArrayList 移除集合中的所有的数据
ArrayList<String> arrayList = new ArrayList<String>();//添加数据arrayList.add("afd");arrayList.add("afd");arrayList.add("afd");System.out.println(arrayList);//[afd, afd, afd]//移除集合中的所有的数据 arrayList.clear();System.out.println(arrayList);//[]
  • 分析其源码我们会发现, 其实是将 集合底层保存数据的数组中的元素设置为了 null , 同时将记录元素个数的变量size的值置为0
//clear功能源码
public void clear() {modCount++;// clear to let GC do its workfor (int i = 0; i < size; i++)elementData[i] = null;size = 0;
}
4 ArrayList 判断是否包含指定的元素

4.1 判断操作

ArrayList<String> arrayList = new ArrayList<String>();//添加数据arrayList.add("afd");arrayList.add("afd");arrayList.add("afd");//判断 集合中是否包含指定的元素 ,饱含返回true ,不包含返回false boolean contains = arrayList.contains("afd");System.out.println(contains);//true

4.2 源码分析

public boolean contains(Object o) {return indexOf(o) >= 0;}
可以发现其内部是调用了indexOf()方法,该方法去数组中查询指定的元素在其中第一次出现的位置 ,如果没有就返回-1,如果有就返回该位置 
5 ArrayList 判断列表中是否有元素(是否不为空)
//集合为空 返回true 不为空返回false
boolean empty = arrayList.isEmpty();

源码分析

//这里的size 是集合对应的保存数据的内容数组的大小
public boolean isEmpty() {return size == 0;
}
6 ArrayList 移除元素
ArrayList<String> arrayList = new ArrayList<String>();//添加数据arrayList.add("afd");arrayList.add("abc");arrayList.add("axc");//方式一 移除0角标的数据arrayList.remove(0);System.out.println(arrayList);//[abc, axc]//方式二 移除数据 "axc"arrayList.remove("axc");System.out.println(arrayList);//[abc]

源码分析


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 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;}
这是两个重载的方法 remove(int index) 是根据传入的角标,根据角标去除对应的数据,最后还是通过System.arraycopy方法来重建新的数组remove(Object o) 是直接移除元素的方法,元素有可能为 null,所以这里有了一个判断 ,最终都是通过 fastRemove(index);方法中的System.arraycopy逻辑来创建新的数组的
7 ArrayList 修改数据
ArrayList<Integer> arrayList = new ArrayList<Integer>();//添加数据for (int i = 0; i <14; i++) {arrayList.add(i);}System.out.println(arrayList);//[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]//修改数据  修改0 号位置上的数据为100Integer set = arrayList.set(0, 100);System.out.println(arrayList);//[100, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

源码分析

public E set(int index, E element) {rangeCheck(index);E oldValue = elementData(index);elementData[index] = element;return oldValue;
}
private void rangeCheck(int index) {if (index >= size)throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
  • 先通过 rangeCheck(index) 方法来检验修改数据传入的角标值是否有效
  • 然后通过elementData(index) 拿到数组中对应角标的数据,并返回去
  • 最后重新对数组中对应角标下进行赋值
8 ArrayList 获取集合中元素的个数
ArrayList<Integer> arrayList = new ArrayList<Integer>();//添加数据for (int i = 0; i <14; i++) {arrayList.add(i);}System.out.println(arrayList);//[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]//获取集合中元素的个数 int size = arrayList.size();System.out.println(size);//14

源码分析

public int size() {return size;}
源码中 直接将记录 元素个数变化的变量size的值返回去
9 ArrayList 转为对应的数组

ArrayList<Integer> arrayList = new ArrayList<Integer>();//添加数据for (int i = 0; i <14; i++) {arrayList.add(i);}System.out.println(arrayList);//[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]//操作方式一 Object[] objArray= arrayList.toArray();for (int i = 0; i < objArray.length; i++) {//取出数据 Integer num = (Integer) objArray[i];System.out.println(num);}//操作方式二//创建将要保存数据的 数组 Integer[] array = new Integer[arrayList.size()];//将集合中的数据转存到数组中 arrayList.toArray(array);
  • 操作方式一中 ,通过toArray()方法是一个Object对象数组,可以在每次取出数据的时候,将数组类型强转

源码分析


public Object[] toArray() {return Arrays.copyOf(elementData, size);
}
  • toArray() 方法是直接使用了 Arrays.copyOf(elementData, size)方法

public <T> T[] toArray(T[] a) {if (a.length < size)// Make a new array of a's runtime type, but my contents:return (T[]) Arrays.copyOf(elementData, size, a.getClass());System.arraycopy(elementData, 0, a, 0, size);if (a.length > size)a[size] = null;return a;
}
  • toArray(T[] a)方法中 当目标数组长度小于集合元素个数的时候,通过 Arrays.copyOf () 来构建赋值数组,否则的话就会通过 System.arraycopy()方法拷贝数组

java ArrayList 概述 与源码简析相关推荐

  1. 【Android项目】本地FM收音机开发及源码简析

    [Android项目]本地FM收音机开发及源码简析 目录 1.概述 2.收音机的基本原理 3.收音机其他信息 RDS功能 4.Android开发FM收音机源码解析 5.App层如何设计本地FM应用 6 ...

  2. 【Golang源码分析】Go Web常用程序包gorilla/mux的使用与源码简析

    目录[阅读时间:约10分钟] 一.概述 二.对比: gorilla/mux与net/http DefaultServeMux 三.简单使用 四.源码简析 1.NewRouter函数 2.HandleF ...

  3. Spring Boot源码简析 @EnableTransactionManagement

    相关阅读 Spring Boot源码简析 事务管理 Spring Boot源码简析 @EnableAspectJAutoProxy Spring Boot源码简析 @EnableAsync Sprin ...

  4. ffmpeg实战教程(十三)iJKPlayer源码简析

    要使用封装优化ijk就必须先了解ffmpeg,然后看ijk对ffmpeg的C层封装! 这是我看ijk源码时候的笔记,比较散乱.不喜勿喷~ ijk源码简析: 1.ijkplayer_jni.c 封装的播 ...

  5. django源码简析——后台程序入口

    django源码简析--后台程序入口 这一年一直在用云笔记,平时记录一些tips或者问题很方便,所以也就不再用博客进行记录,还是想把最近学习到的一些东西和大家作以分享,也能够对自己做一个总结.工作中主 ...

  6. (Ajax)axios源码简析(三)——请求与取消请求

    传送门: axios源码简析(一)--axios入口文件 axios源码简析(二)--Axios类与拦截器 axios源码简析(三)--请求与取消请求 请求过程 在Axios.prototype.re ...

  7. Log-Pilot 源码简析

    Log-Pilot 源码简析 简单介绍 源码简析 Pilot结构体 Piloter接口 main函数 Pilot.Run Pilot.New Pilot.watch Pilot.processEven ...

  8. java arraylist 赋值_ArrayList源码解析,老哥,来一起复习一哈?

    点击上方"码农沉思录",选择"设为星标" 优质文章,及时送达 前言 JDK源码解析系列文章,都是基于JDK8分析的,虽然JDK14已经出来,但是JDK8我还不会 ...

  9. JVM源码简析(楔子)-对象内存分配过程和PS回收器中YGC触发FGC的现象

    前言 想要搞明白Java对象内存申请过程的原因,是因为第一次接触线上GC日志的时候,发现了一些很奇怪的现象,就是young gc触发了full gc.为了搞清楚这个现象,得先要来个测试去复现. 复现现 ...

最新文章

  1. java set 包含_Java Set.contains()方法:判断Set集合是否包含指定的对象
  2. mongo数据库单节点搭建
  3. dataframe进行groupby后画图坐标轴刻度问题
  4. 事务管理:事务的状态相关知识笔记
  5. linux shell 用sed命令在文本的行尾或行首添加字符
  6. 分组求和计算_excel聚合、累计、分组累计、分组聚合函数
  7. ios更新了系统无服务器,iPhone更新iOS 12.0.1系统失败怎么办?
  8. python123输出hello world_2-python学习——hello world
  9. 最短路径例题(Floyd、Dijkstra)
  10. 公务员从事计算机网络工作,干程序员好,还是从事公务员更有前途?网友:要是我就当公务员!...
  11. OBS无延迟视频直播完整教程(组图)
  12. 【Web渗透测试】—Web漏洞
  13. 「Python海龟画图」利用海龟画笔绘制谢尔宾斯基三角形
  14. 批量下载网页上ts视频文件(撸sir!你还在为下载小电影而苦恼吗?)
  15. 赛码网在线考试无法使用外接摄像头解决方案
  16. 自动反冲洗叠片过滤器
  17. 微机原理课程设计--计算器
  18. 基于Jetson AGX Xavier GMSL9296硬件设计与软硬件调试
  19. 内部泄露版!互联网大厂的薪资和职级一览
  20. 从零编写linux0.11 - 第三章 printk函数

热门文章

  1. 边缘深度学习设备基准评测:英伟达Jetson Nano胜出
  2. ThunderNet:国防科大、旷视提出首个在ARM上实时运行的通用目标检测算法
  3. 收藏 | 机器学习领域必知必会的12种概率分布(附Python代码实现)
  4. 创新!谷歌大改Transformer注意力
  5. PyTorch | 通过torch.normal()创建概率分布的张量 | torch.normal()如何使用?torch.normal()使用方法 | torch.normal()例子
  6. CVPR2019| ADCrowdNet: 用于人群理解的可变形卷积网络
  7. Python中的operator.itemgetter函数
  8. 从零开始编写深度学习库(五)ConvolutionLayer CPU编写
  9. python工程师工资状况_【python工程师工资|python工程师待遇怎么样】-看准网
  10. python异步回调实现原理_快速理解Python异步编程的基本原理