关键常量:

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、构造方法

public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
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);
}
}
public ArrayList(Collection<? extends E> c) { //通过一个集合构造数组
elementData = c.toArray();
if ((size = elementData.length) != ) { //参数集合不为空,则将实例构造成Object[]
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else { //参数集合为空,则将实例构造成默认空数组
this.elementData = EMPTY_ELEMENTDATA;
}
}

2、新增

public boolean add(E e) {
ensureCapacityInternal(size + ); //扩容操作
elementData[size++] = e;
return true;
}
public void add(int index, E element) {  //添加元素到指定位置
rangeCheckForAdd(index); //检查index是否越界 ensureCapacityInternal(size + );
System.arraycopy(elementData, index, elementData, index + ,size - index);
elementData[index] = element;
size++;
}
public boolean addAll(Collection<? extends E> c) { //将参数集合添加至实例
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew);
System.arraycopy(a, , elementData, size, numNew);
size += numNew;
return numNew != ;
}
public boolean addAll(int index, Collection<? extends E> c) { //将参数集合添加至实例指定位置
rangeCheckForAdd(index); //检查index是否越界 Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew); // Increments modCount int numMoved = size - index; //这里要注意,插入前会将原数组从index位置分开
if (numMoved > )
System.arraycopy(elementData, index, elementData, index + numNew,
numMoved); System.arraycopy(a, , elementData, index, numNew);
size += numNew;
return numNew != ;
}

3、覆盖

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

4、读取

 public E get(int index) {
rangeCheck(index); return elementData(index);
}

5、删除

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, //删除元素之后会将index之后的元素依次向前一位
numMoved);
elementData[--size] = null; // clear to let GC do its work return 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;
}

6、清空

public void clear() {
modCount++; for (int i = 0; i < size; i++)
elementData[i] = null; size = 0;
}

7、扩容

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

8、Fail-Fast机制

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

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. errored out in DoExecute, couldn't PrepareToExecuteJITExpression

    error: Couldn't materialize struct: size of variable <varName> disagrees with the ValueObject' ...

  2. HMM基本原理及其实现(隐马尔科夫模型)

    HMM(隐马尔科夫模型)基本原理及其实现 HMM基本原理 Markov链:如果一个过程的“将来”仅依赖“现在”而不依赖“过去”,则此过程具有马尔可夫性,或称此过程为马尔可夫过程.马尔可夫链是时间和状态 ...

  3. 第一章 --- 关于Javascript 设计模式 之 单例模式

    首先我们对单例模式先进行理论上的讲解,接下来,我们再通过具体的代码示例,来讲解,这个单例模式的使用场景和这种模式的优缺点 (这个系列的所有关于设计模式的都是面向Javascript) 一.理论定义: ...

  4. QEMU 中的QOM分析

    QOM (QEMU Object Model) 类对象的意义: 1:每个类型在系统中都只有且只有一个类对象 2:当系统中的某个类型的实例对象都被销毁了,那么系统就会销毁该类对象了 3:类对象的作用:负 ...

  5. String StringBuffer StringBuilder

    package com.test; import java.util.Date; /*** * * // 输出的结果是:// 来一个测试// 来一个测试如果只输出这句就证明了String是不可变的// ...

  6. 【Android自学日记】两种适配器的使用

    ArrayAdapter适配器: (1)用于显示基本的文字内容 (2)基本使用过程:新建适配器---创建或加载数据源---适配器加载数据源---视图加载适配器 ArrayAdapter(上下文,当前L ...

  7. Reverse Integer LeetCode Java

    Reverse digits of an integer. Example1: x = 123, return 321Example2: x = -123, return -321 public cl ...

  8. Activity系列讲解---数据传递

    在Android中,不同的Activity实例可能运行在一个进程中,也可能运行在不同的进程中.因此需要一种特别的机制帮助我们在Activity之间传递消息.Android中通过Intent对象来表示一 ...

  9. CapsLock与ctrl的键位修改

    windows下修改方式: linux下修改方式: 在用户目录下新建文档命名为keychange.sh 编辑以下内容: remove Lock = Caps_Lock remove Control = ...

  10. 得到 window.open 新页面中的数据

    1.htm 页面 单击按  '钮后'  调用window.open方法,开启新窗口  2.htm 想实现---------------------- 在2.htm页面单击按钮 将相应的数据返回到 1. ...