关键常量:

private static final int DEFAULT_CAPACITY = 10; 当没有其他参数影响数组大小时的默认数组大小
private static final Object[] EMPTY_ELEMENTDATA = {}; 如果elementData用这个变量初始化,则DEFAULT_CAPACITY不会参与数组大小的运算
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; 如果elementData用这个变量初始化,则DEFAULT_CAPACITY会参与数组大小的运算,只有ArrayList()中有调用
transient Object[] elementData; 实际存储数据的数组
private int size; 数组大小
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; 之所以减8是因为不同的vm有不同的保留字会占用一部分容量
 

概述:

  ArrayList是基于数组实现的一个有序的列表,允许添加null值.除了List接口中的方法外,还实现了一些操作数组元素和大小的方法,具体下面会列举。每个ArrayList实例都有一个元素数,即size属性,这个属性标注了在实例中包含了多少个元素,这些元素存储在elementData这个数组中,当实例的容量不足时,会调用grow方法进行扩容,通常情况下每次扩大一半容量,但是有两种特殊情况,一种是手动指定的容量大于当前容量的1.5倍时会按照指定容量扩容,另一种是当前容量的1.5倍大于MAX_ARRAY_SIZE这个值的时候会扩容至Integer.MAX_VALUE或MAX_ARRAY_SIZE。
 

主要方法:

1、构造方法

  1. public ArrayList() {
  2. this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
  3. }
  4. public ArrayList(int initialCapacity) { //指定容量
  5. if (initialCapacity > ) { //指定容量>0,则按照指定的容量构建数组
  6. this.elementData = new Object[initialCapacity];
  7. } else if (initialCapacity == ) { //指定容量=0,则构造默认空数组
  8. this.elementData = EMPTY_ELEMENTDATA;
  9. } else {
  10. throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);
  11. }
  12. }
  13. public ArrayList(Collection<? extends E> c) { //通过一个集合构造数组
  14. elementData = c.toArray();
  15. if ((size = elementData.length) != ) { //参数集合不为空,则将实例构造成Object[]
  16. if (elementData.getClass() != Object[].class)
  17. elementData = Arrays.copyOf(elementData, size, Object[].class);
  18. } else { //参数集合为空,则将实例构造成默认空数组
  19. this.elementData = EMPTY_ELEMENTDATA;
  20. }
  21. }

2、新增

  1. public boolean add(E e) {
  2. ensureCapacityInternal(size + ); //扩容操作
  3. elementData[size++] = e;
  4. return true;
  5. }
  6. public void add(int index, E element) {  //添加元素到指定位置
  7. rangeCheckForAdd(index); //检查index是否越界
  8.  
  9. ensureCapacityInternal(size + );
  10. System.arraycopy(elementData, index, elementData, index + ,size - index);
  11. elementData[index] = element;
  12. size++;
  13. }
  14. public boolean addAll(Collection<? extends E> c) { //将参数集合添加至实例
  15. Object[] a = c.toArray();
  16. int numNew = a.length;
  17. ensureCapacityInternal(size + numNew);
  18. System.arraycopy(a, , elementData, size, numNew);
  19. size += numNew;
  20. return numNew != ;
  21. }
  22. public boolean addAll(int index, Collection<? extends E> c) { //将参数集合添加至实例指定位置
  23. rangeCheckForAdd(index); //检查index是否越界
  24.  
  25. Object[] a = c.toArray();
  26. int numNew = a.length;
  27. ensureCapacityInternal(size + numNew); // Increments modCount
  28.  
  29. int numMoved = size - index; //这里要注意,插入前会将原数组从index位置分开
  30. if (numMoved > )
  31. System.arraycopy(elementData, index, elementData, index + numNew,
  32. numMoved);
  33.  
  34. System.arraycopy(a, , elementData, index, numNew);
  35. size += numNew;
  36. return numNew != ;
  37. }

3、覆盖

  1. public E set(int index, E element) { //新增会将index位置之后的元素依次后移,而覆盖会将index位置的元素替换,对其他位置的元素没有影响
  2. rangeCheck(index);
  3.  
  4. E oldValue = elementData(index);
  5. elementData[index] = element;
  6. return oldValue;
  7. }

4、读取

  1. public E get(int index) {
  2. rangeCheck(index);
  3.  
  4. return elementData(index);
  5. }

5、删除

  1. public E remove(int index) {
  2. rangeCheck(index);
  3.  
  4. modCount++;
  5. E oldValue = elementData(index);
  6.  
  7. int numMoved = size - index - 1;
  8. if (numMoved > 0)
  9. System.arraycopy(elementData, index+1, elementData, index, //删除元素之后会将index之后的元素依次向前一位
  10. numMoved);
  11. elementData[--size] = null; // clear to let GC do its work
  12.  
  13. return oldValue;
  14. }
  15. public boolean remove(Object o) {
  16. if (o == null) {
  17. for (int index = 0; index < size; index++) //遍历数组直到找到指定元素并删除
  18. if (elementData[index] == null) {
  19. fastRemove(index);
  20. return true;
  21. }
  22. } else {
  23. for (int index = 0; index < size; index++) //遍历数组直到找到指定元素并删除
  24. if (o.equals(elementData[index])) {
  25. fastRemove(index);
  26. return true;
  27. }
  28. }
  29. return false;
  30. }

6、清空

  1. public void clear() {
  2. modCount++;
  3.  
  4. for (int i = 0; i < size; i++)
  5. elementData[i] = null;
  6.  
  7. size = 0;
  8. }

7、扩容

  1. private void ensureCapacityInternal(int minCapacity) {
  2. if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //当使用第一种构造方法时,第一次执行扩容方法会进入这个分支,将容量扩展为默认大小(10)
  3. minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
  4. }
  5. ensureExplicitCapacity(minCapacity);
  6. }
  7.  
  8. private void ensureExplicitCapacity(int minCapacity) {
  9. modCount++;
  10. if (minCapacity - elementData.length > 0) //如果参数长度大于数组长度则会扩容
  11. grow(minCapacity);
  12. }
  13. private void grow(int minCapacity) {
  14. int oldCapacity = elementData.length;
  15. int newCapacity = oldCapacity + (oldCapacity >> 1); //默认每次增长为1.5倍
  16. if (newCapacity - minCapacity < 0) //特例1:参数大于数组长度的1.5倍,此时按照参数扩容
  17. newCapacity = minCapacity;
  18. if (newCapacity - MAX_ARRAY_SIZE > 0) //特例2:数组长度的1.5倍大于MAX_ARRAY_SIZE,此时将数组扩容至MAX_ARRAY_SIZE 或Integer.MAX_VALUE
  19. newCapacity = hugeCapacity(minCapacity);
  20. elementData = Arrays.copyOf(elementData, newCapacity);
  21. }

8、Fail-Fast机制

ArrayList的迭代器也具备快速失败机制,具体是通过checkForComodification()进行控制:
  1. final void checkForComodification() {
  2. if (modCount != expectedModCount)
  3. throw new ConcurrentModificationException();
  4. }
如果并发线程对实例进行增删操作,则迭代器会抛出异常以防止在不确定的时间发生某种行为带来的未知风险
 

ArrayList源码阅读笔记(基于JDk1.8)的更多相关文章

  1. ArrayList源码阅读笔记(1.8)

    目录 ArrayList类的注解阅读 ArrayList类的定义 属性的定义 ArrayList构造器 核心方法 普通方法 迭代器(iterator&ListIterator)实现 最后声明 ...

  2. ArrayList源码分析笔记(jdk1.8)

    1.特点: ArrayList 是一个动态数组,它是线程不安全的,允许元素为null 可重复,插入有序 读写快,增删慢 扩容:默认容量 10,默认扩容1.5倍 建议指定容量大小,减少扩容带来的性能消耗 ...

  3. ArrayList源码分析(基于JDK1.8)

    public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess ...

  4. ArrayList源码阅读笔记

    ArrayList ArrayList继承自AbstractList抽象类,实现了RandomAccess, Cloneable, java.io.Serializable接口,其中RandomAcc ...

  5. java8 ArrayList源码阅读

    转载自 java8 ArrayList源码阅读 本文基于jdk1.8 JavaCollection库中有三类:List,Queue,Set 其中List,有三个子实现类:ArrayList,Vecto ...

  6. jdk源码阅读笔记-LinkedHashMap

    Map是Java collection framework 中重要的组成部分,特别是HashMap是在我们在日常的开发的过程中使用的最多的一个集合.但是遗憾的是,存放在HashMap中元素都是无序的, ...

  7. CopyOnWriteArrayList源码阅读笔记

    简介 ArrayList是开发中使用比较多的集合,它不是线程安全的,CopyOnWriteArrayList就是线程安全版本的ArrayList.CopyOnWriteArrayList同样是通过数组 ...

  8. JDK1.8源码阅读笔记(2) AtomicInteger AtomicLong AtomicBoolean原子类

    JDK1.8源码阅读笔记(2) AtomicInteger AtomicLong AtomicBoolean原子类 Unsafe Java中无法直接操作一块内存区域,不能像C++中那样可以自己申请内存 ...

  9. JDK1.8源码阅读笔记(1)Object类

    JDK1.8源码阅读笔记(1)Object类 ​ Object 类属于 java.lang 包,此包下的所有类在使⽤时⽆需⼿动导⼊,系统会在程序编译期间⾃动 导⼊.Object 类是所有类的基类,当⼀ ...

随机推荐

  1. MongoDB【第一篇】MongodDB初识

    NoSQL介绍 一.NoSQL简介 NoSQL,全称是”Not Only Sql”,指的是非关系型的数据库. 非关系型数据库主要有这些特点:非关系型的.分布式的.开源的.水平可扩展的. 原始的目的是为 ...

  2. C# 全角和半角转换以及判断的简单代码

    在C#中判断和转换全角半角的方法 1. 判断是否为全角半角 全角占用二个字节 半角占用一个字节 用string.length 和System.text.Encoding.Default.GetByte ...

  3. Altium Designer 的entry sheet ,offsheet和port作用(转载)

    1.图纸结构 图纸包括两种结构关系: 一种是层次式图纸,该连接关系是纵向的,也就是某一层次的图纸只能和相邻的上级或下级有关系: 另一种是扁平式图纸,该连接关系是横向的,任何两张图纸之间都可以建立信号连 ...

  4. nodeJS爬虫---慕课网

    源代码一(爬取html源码) //引入http模块var http = require('http');//引入url地址var url = 'http://www.imooc.com/learn/2 ...

  5. Android消息处理

    基本概念: Message:消息,其中包含了消息ID.what,消息处理对象.obj以及处理的数据.arg1.arg2等,由MessageQueue统一列队,终由Handler处理. Handler: ...

  6. mybatis逆向工程生成JavaBean、dao、mapper generatorSqlmapCustom

    import java.io.File; import java.util.ArrayList; import java.util.List; import org.mybatis.generator ...

  7. svn sync主从同步学习

    svn备份的方式有三种: 1svnadmin dump 2)svnadmin hotcopy 3)svnsync.  优缺点分析============== 第一种svnadmin dump是官方推荐 ...

  8. angularJS实践过程中出现的问题总结

    同名服务 在一次项目里,之前是同事写的.我有一次在异步获取服务器上的数据时,习惯把api地址写在一个服务Store里,但是程序总是返回Store.api.get()里的get is undefined ...

  9. WebView-存在的内存泄漏

    0. Notice - earlier version 要使用WebView不造成内存泄漏,首先应该做的就是不能在xml中定义webview节点,而是在需要的时候动态生成.即:可以在使用WebView ...

  10. asp.net 文件下载(txt,rar,pdf,word,excel,ppt)

    aspx 文件下载说起来一点都不难,但是在做的过程中还是遇到了一些小小的问题,就是因为这些小小的问题,导致解决起来实在是太难了,其中一个就是Response.End();导致下载文件出现线程终止的情况 ...