版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_40254498/article/details/81383693

ArrayList

ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存。

  • ArrayList不是线程安全的,只能用在单线程环境
  • 多线程环境下可以考虑用Collections.synchronizedList(List l)函数返回一个线程安全的ArrayList类
  • 也可以使用concurrent并发包下的CopyOnWriteArrayList类
  • ArrayList实现了Serializable接口,因此它支持序列化,能够通过序列化传输
  • 实现了RandomAccess接口,支持快速随机访问,实际上就是通过下标序号进行快速访问
  • 实现了Cloneable接口,能被克隆

根据JDK版本的不同 ,构造方法也不同

/**
*   JDK 1.8
*/
/*** Default initial capacity.*/
private static final int DEFAULT_CAPACITY = 10;
/*** Shared empty array instance used for default sized empty instances. We* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when* first element is added.*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/*** Shared empty array instance used for empty instances.*/
private static final Object[] EMPTY_ELEMENTDATA = {};/*** 上面这个对象数组就是其存储元素的数据结构,前面有一个java关键字transient* 这个关键字是去序列化的意思,即,在这个类序列化后保存到磁盘或者输出到输出流的时候* 这个对象数组是不被保存或者输出的。(这个不是下面的翻译,对transient解释)* * The array buffer into which the elements of the ArrayList are stored.* The capacity of the ArrayList is the length of this array buffer. Any* empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA* will be expanded to DEFAULT_CAPACITY when the first element is added.*/
transient Object[] elementData; // non-private to simplify nested class access/*** ArrayList带容量大小的构造函数。  * Constructs an empty list with the specified initial capacity.** @param  initialCapacity  the initial capacity of the list* @throws IllegalArgumentException if the specified initial capacity*         is negative*/
public ArrayList(int initialCapacity) {if (initialCapacity > 0) {this.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {this.elementData = EMPTY_ELEMENTDATA;} else {throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);}
}/*** 无参构造方法构造的ArrayList的默认返回空数组* Constructs an empty list with an initial capacity of ten.*/
public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}/*** 带有Collection参数的构造方法* Constructs a list containing the elements of the specified* collection, in the order they are returned by the collection's* iterator.** @param c the collection whose elements are to be placed into this list* @throws NullPointerException if the specified collection is null*/
public ArrayList(Collection<? extends E> c) {elementData = c.toArray();if ((size = elementData.length) != 0) {// c.toArray might (incorrectly) not return Object[] (see 6260652)if (elementData.getClass() != Object[].class)elementData = Arrays.copyOf(elementData, size, Object[].class);} else {// replace with empty array.this.elementData = EMPTY_ELEMENTDATA;}
}/**
* JDK 1.7/1.6
*/
/**
* Constructs an empty list with the specified initial capacity. * * @param  initialCapacity  the initial capacity of the list * @throws IllegalArgumentException if the specified initial capacity *         is negative */  public ArrayList(int initialCapacity) {  super();  if (initialCapacity < 0)  throw new IllegalArgumentException("Illegal Capacity: "+  initialCapacity);  this.elementData = new Object[initialCapacity];  }  /** * 无参构造直接返回了this(10);默认10 这也是与1.8不同的地方* Constructs an empty list with an initial capacity of ten. */  public ArrayList() {  this(10);  }  /** * Constructs a list containing the elements of the specified * collection, in the order they are returned by the collection's * iterator. * 在这1.8也多了一个判断* @param c the collection whose elements are to be placed into this list * @throws NullPointerException if the specified collection is null */  public ArrayList(Collection<? extends E> c) {  elementData = c.toArray();  size = elementData.length;  // c.toArray might (incorrectly) not return Object[] (see 6260652)  if (elementData.getClass() != Object[].class)  elementData = Arrays.copyOf(elementData, size, Object[].class);  }

为什么用到 transient?

这就跟这个ArrayList的特性有关,我们知道ArrayList的容量,也就是这个数组的容量,一般都是预留一些容量,等到容量不够时再拓展,那么就会出现容量还有冗余的情况,如果这时候进行序列化,整个数组都会被序列化,连后面没有意义空元素的也被序列化。这些是不应该被存储的。所以java的设计者,就为这个类提供了一个writeObject方法,在实现了Serializable接口的类,如果这个类提供了writeObject方法,那么在进行序列化的时候就会通过writeObject方法进行序列化,所以ArrayList的writeObject方法就会显式的为每个实际的数组元素进行序列化,只序列化有用的元素。


为什么源码中大量地调用了Arrays.copyof()和System.arraycopy()方法?

public static <T> T[] copyOf(T[] original, int newLength) {return (T[]) copyOf(original, newLength, original.getClass());
}
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {T[] copy = ((Object)newType == (Object)Object[].class)? (T[]) new Object[newLength]: (T[]) Array.newInstance(newType.getComponentType(), newLength);System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));return copy;
}

最后都调用了System.arraycopy()方法。

/**
* 该方法被标记了native,调用了系统的C/C++代码,在JDK中是看不到的,
* 但在openJDK中可以看到其源码。该函数实际上最终调用了C语言的memmove()函数,
* 因此它可以保证同一个数组内元素的正确复制 和移动,比一般的复制方法的实现效率要高很多,
* 很适合用来批量处理数组。Java强烈推荐在复制大量数组元素时用该方法,以取得更高的效率。
* 这也说明了ArrayList 与数组
*/
public static native void arraycopy(Object src,  int  srcPos,Object dest, int destPos,int length);

JDK1.6 开始扩容办法也不一样

/** * JDK1.6* Increases the capacity of this <tt>ArrayList</tt> instance, if * necessary, to ensure that it can hold at least the number of elements * specified by the minimum capacity argument. * * @param   minCapacity   the desired minimum capacity */  public void ensureCapacity(int minCapacity) {  modCount++;  int oldCapacity = elementData.length;  if (minCapacity > oldCapacity) {  Object oldData[] = elementData;  int newCapacity = (oldCapacity * 3)/2 + 1;  if (newCapacity < minCapacity)  newCapacity = minCapacity;  // minCapacity is usually close to size, so this is a win:  elementData = Arrays.copyOf(elementData, newCapacity);  }  } /*** JDK1.8 *//*** The maximum size of array to allocate.* Some VMs reserve some header words in an array.* Attempts to allocate larger arrays may result in* OutOfMemoryError: Requested array size exceeds VM limit*/private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;/*** Increases the capacity to ensure that it can hold at least the* number of elements specified by the minimum capacity argument.** @param minCapacity the desired minimum capacity*/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);}private static int hugeCapacity(int minCapacity) {if (minCapacity < 0) // overflowthrow new OutOfMemoryError();return (minCapacity > MAX_ARRAY_SIZE) ?Integer.MAX_VALUE :MAX_ARRAY_SIZE;}
  • 1.7JDK开始使用的是位运算
  • 在算出newCapacity时,其没有和ArrayList所定义的MAX_ARRAY_SIZE作比较,为什么没有进行比较呢,原因是jdk1.6没有定义这个MAX_ARRAY_SIZE最大容量,也就是说,其没有最大容量限制的,但是jdk1.7以上做了一个改进,进行了容量限制。

Java 集合中常见 checkForComodification()方法的作用? modCount和expectedModCount作用?


ArrayList 快速访问

ArrayList基于数组实现,可以通过下标索引直接查找到指定位置的元素,因此查找效率高,但每次插入或删除元素,就要大量地移动元素,插入删除元素的效率低。

/**
* 先检查索引 然后校验操作正确
*/
public E get(int var1) {this.rangeCheck(var1);return this.elementData(var1);
}

ArrayList 源码阅读记录相关推荐

  1. r8169驱动源码阅读记录

    r8169驱动源码阅读记录 初始化 发包 收包 源码地址:linux-4.19.90\drivers\net\ethernet\realtek\r8169.c 源码阅读环境:Windows 搭建 op ...

  2. Tomcat 源码阅读记录(1)

    使用Ant 工具进行编译打包. 源码对应关系: SourceCode TargetPackage /bin /bin /conf /conf /java /lib/* /Modules 依赖包 /re ...

  3. ArrayList源码阅读

    前言 数组是我们最常用最简单的数据结构,Java里对数组做了一个简单的包装,就是ArrayList,提供自动扩容的功能. 最常用法 list在我们日常代码中最为常用的做法是创建一个list,放入数据, ...

  4. WebRTC系列 -- iOS ADM音频数据流处理流程及源码阅读记录

    文章目录 1. 播放数据 1.1 数据流的中转中心-AudioTransportImpl 1.2 混音及数据获取 2 音频录制数据 2.1 初始化音频帧及设置相关属性 2.2 混音及重采样 2.3 处 ...

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

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

  6. focal loss dice loss源码_0815——W2V的TF源码阅读

    昨天开始看text matching的一个很好的资源,有文献有讲解有代码 今天看了DRCN的网络结构部分,代码部分还在进行中... 贴上原作者的地址: 文本匹配模型之DRCN - Welcome to ...

  7. 【源码阅读】Java集合之一 - ArrayList源码深度解读

    Java 源码阅读的第一步是Collection框架源码,这也是面试基础中的基础: 针对Collection的源码阅读写一个系列的文章,从ArrayList开始第一篇. ---@pdai JDK版本 ...

  8. 应用监控CAT之cat-client源码阅读(一)

    CAT 由大众点评开发的,基于 Java 的实时应用监控平台,包括实时应用监控,业务监控.对于及时发现线上问题非常有用.(不知道大家有没有在用) 应用自然是最初级的,用完之后,还想了解下其背后的原理, ...

  9. mybatis源码阅读(八) ---Interceptor了解一下

    转载自  mybatis源码阅读(八) ---Interceptor了解一下 1 Intercetor MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用.默认情况下,MyBatis允许 ...

最新文章

  1. 【100题】第十五题(树的镜像问题)
  2. Mysql---Centos7软件安装
  3. sed文本处理常见用法
  4. os sys hashlib
  5. URAL 1106 Two Teams (DFS)
  6. Eclipse 一直提示 loading descriptor for 的解决方法
  7. 基于PHP的学生选课管理系统
  8. 景区分时实名预约系统
  9. 3D打印是什么?如何工作的?
  10. C#小游戏,拼音打字练习
  11. 如何用html来编写ppt,impress.js——用HTML“写”幻灯片
  12. 面向对象与面向过程的区别与联系
  13. 蓝桥杯_横向打印二叉树
  14. 天猫精灵连接蓝牙摸索4 STM32单片机和TG7100B实现数据上发和播报
  15. 计算机应用研究、计算机工程与应用、计算机科学与探索投稿经验
  16. 算法总结-字典树(正在更新)
  17. HFSS低版本如何打开高版本的文件
  18. 安装方正电子教室 缺少dll
  19. leetcode每日一道(3)最多能有多少个点位于同一直线上
  20. php网站统一登录,php新浪通行证、新浪微博模拟统一登录(后台网页抓取版)2016

热门文章

  1. “为啥Kaggle奖金那么少?”一场25000美元的比赛,却因“抠门”引发激烈讨论...
  2. java 与 |与||的区别
  3. WPF中如何将ListViewItem双击事件绑定到Command
  4. ORACL内部异常:
  5. Java基础:Java变量、数据类型、运算符(2)
  6. Web APi之控制器创建过程及原理解析(八)
  7. LeetCode - Department Highest Salary
  8. C#三种判断字符是否为汉字的方法
  9. 【随想】_无关技术_你是合格的项目经理人吗?
  10. 对 makefile 中 .NOTPARALLE 的学习体会