> 文章列表 > ArrayList的深入理解

ArrayList的深入理解

ArrayList的深入理解

ArrayList的源码解析

  • 1. 实例化无参构造器
  • 2. add()方法
    • 2.1. add()List的扩容
  • 3. get()方法
  • 4. remove()
  • 5. modCount++ 的作用(面试题)
  • 5. 手写简单List实现存储删除

1. 实例化无参构造器

  • Arraylist作为日常最一个类,内部是动态扩容数组,与普通数组的区别就是它是没有固定大小的限制,并且是线程不安全的
  • 先看实例化的无参构造器
    ArrayList的深入理解
  • 执行实例化是要调用其无参构造方法,无参构造方法就是给elementData初始化分配地址值,也就是实例化一下,不初始化的默认值为null
    ArrayList的深入理解
 transient Object[] elementData; // non-private to simplify nested class accessprivate static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

2. add()方法

ArrayList的深入理解

  • 在认识一下源码中的Size,也就是数组的长度大小
  • 源码中的DEFAULT_CAPACITY 也就是数组的默认值的大小
    ArrayList的深入理解

ArrayList的深入理解

  • size默认的初始化是0,调用的是ensureCapacityInternal()传递的是长度+1的数值
    ArrayList的深入理解
    ArrayList的深入理解
  • 看一下方法,传递的参数是elementData,也就是list存储元素的数组和minCapacity,也就是长度+1数组的长度
  • 这个判断是判断地址值是否相等,相等的话,在(默认值10,和传递的minCapacity 是数字的默认值+1),现在是返回的是10,因为10大
    ArrayList的深入理解
  • modCount++; 这个操作,最后在说
  • minCapacity是刚才调用的calculateCapacity方法返回的默认值和传递的大小中的最大值,目前是10
  • 判断:如果10(默认长度)-elementData.length(默认值0)>0,这个就是ArrayList中核心的一个数组扩容的方法,超过了数组的容量限制执行扩容方法
    ArrayList的深入理解
    grow方法
    oldCapacity 是数组原来的长度,现在是0
    newCapacity是数组新的长度,用老数组位移得到
    如果新数组长度-minCapacity(10初始化)=0,新的数组长度就是默认值10初始化默认值10
    最后就是拷贝一份,将原elementData拷贝出来一份默认值为10的数组
    ArrayList的深入理解
  • 致此,这个阶段就完成了,第一次add的ensureCapacityInternal方法的作用是初始化了一个长度为10的数组
  • 然后将元素添加到数组之中返回true
    ArrayList的深入理解

2.1. add()List的扩容

  • List的扩容机制体现在这里 ,第一次初始化需要扩容数组长度是10
  • 然后以后每次扩容依靠的是,是够超过了数组的容量,然后进行扩容,扩容执行的是grow方法,非扩容直接添加
    ArrayList的深入理解
    ArrayList的深入理解
  • 扩容扩原数组的1.5倍大小,然后copy一个新的数组,进行返回
    ArrayList的深入理解

3. get()方法

  • get方法就是,传递的index超过了数组的长度就抛异常
  • return elementData(index);
    ArrayList的深入理解

4. remove()

  • remove方法其实就是一个拷贝的过程
第一个参数默认是src 来源数组 类型为数组
第二个参数默认是srcPos 从来源数组开始复制的位置 类型为整行(其实就是下标)
第三个参数默认是dest 目标数组 类型为数组
第四个参数默认是destPos 目标数组接收起始位置类型为整行(其实就是下标)
第五个参数默认是length 复制的长度

ArrayList的深入理解

5. modCount++ 的作用(面试题)

  • 通过看源码发现add和删除等一些地方有modCount++这个代码,这个代码的作用是,在遍历中,为了避免一边修改数据,一边拿数据,进而造成的数据混乱
 public void 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();}}

5. 手写简单List实现存储删除

package com.rj.bd.Test;import lombok.Data;import java.util.Arrays;/* @author LXY* @desc* @time 2023--04--10--10:46*/
public class YList<T> {//初始化private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};//数组初始化默认大小private  static  final  int DEFAULT_CAPACITY =10;Object[] elementData;//初始化0private  int Size;//添加方法public  void add(T e){ensureCapacityInternal(Size+1);elementData[Size++]=e;}public void  remove(int 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 work}//添加方法public  T get(int index){if (elementData.length-index<0){try {throw  new Exception("数组越界");} catch (Exception e) {e.printStackTrace();}}return (T) elementData[index];}//判断最大值private int ensureCapacityMax(int minsize){return Math.max(minsize, Size);}private void ensureCapacityInternal(int minsize) {int indexs = ensureCapacityMax(minsize);if (indexs>elementData.length){grep(indexs);}}//扩容方法private void grep(int minCapacity) {//原来的长度int oldCapacity=elementData.length;int newCapacity= oldCapacity + (oldCapacity >> 1);if (newCapacity-minCapacity<0){newCapacity=DEFAULT_CAPACITY;}elementData = Arrays.copyOf(elementData, newCapacity);}//无参构造器,初始化public  YList (){elementData=DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}}