首页 > 编程语言 >Java集合 —— ArrayList详解(源码)

Java集合 —— ArrayList详解(源码)

时间:2025-01-03 16:47:08浏览次数:12  
标签:Object Java int ArrayList elementData 源码 数组 size

我这里阅读的是JDK17关于ArrayList的源码,不过思路都是一样的

简介

  ArrayList 是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。

  ArrayList 继承了 AbstractList ,并实现了 List 接口。

属性设置

// 序列化 Id
private static final long serialVersionUID = 8683452581122892189L;
// 默认初始化容量
private static final int DEFAULT_CAPACITY = 10;
// 空数组
private static final Object[] EMPTY_ELEMENTDATA = {};
// 空数组(如果使用默认构造函数创建,则默认对象内容默认是该值)
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
// 当前数据对象存放地方
transient Object[] elementData; 
// 当前数组长度
private int size;


构造方法

  • 带初始值的构造方法

传入一个初始值,对其进行判断,如果大于0,使用用户的参数初始化,如果等于0,使用空值,都不满足,抛出异常

  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时,不传入参数,直接赋予空值

public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
  • 传入参数为集合的构造方法

这里先将集合转换成数组,在size进行非空判断后,如果传入的参数为 ArrayList,直接将转换为的数组赋值给elementData,如果是其他类型,将转换为的数组复制到新的Object数组中并将其赋值给elementData,如果size为空,赋值为空

public ArrayList(Collection<? extends E> c) {
    Object[] a = c.toArray();
    if ((size = a.length) != 0) {
        if (c.getClass() == ArrayList.class) {
            elementData = a;
        } else {
            elementData = Arrays.copyOf(a, size, Object[].class);
        }
    } else {
        // replace with empty array.
        elementData = EMPTY_ELEMENTDATA;
    }
}


添加

  • 无返回值的添加方法,接收三个参数
  • E e:要添加的元素

  • Object[] elementData:ArrayList 内部存储元素的数组

  • int s:当前 ArrayList 的大小(即元素个数)

将元素e添加到数组elementData中,如果长度不够,调用row()方法进行扩容

private void add(E e, Object[] elementData, int s) {
    if (s == elementData.length)
        elementData = grow();
    elementData[s] = e;
    size = s + 1;
}
  • 返回布尔值的添加方法,接收一个参数

和上面的E是一样的,modCount是 AbstractList 中的一个属性,代表修改计数器,对修改次数进行记录,通过上一个add(E e, Object[] elementData, int s)进行添加

public boolean add(E e) {
    modCount++;
    add(e, elementData, size);
    return true;
}
  • 插入到指定位置的添加方法

通过rangeCheckForAdd()方法对索引进行检查,如果小于0或者大于size,抛出异常,对修改次数进行修改,检查数组是否需要扩容,之后对元素进行移动,插入新元素,修改size

public void add(int index, E element) {
    rangeCheckForAdd(index);
    modCount++;
    final int s;
    Object[] elementData;
    if ((s = size) == (elementData = this.elementData).length)
        elementData = grow();
    System.arraycopy(elementData, index,
                     elementData, index + 1,
                     s - index);
    elementData[index] = element;
    size = s + 1;
}


扩容

  • 对ArrayList的内部数组进行扩容
  • 如果当前数组容量大于 0,按一定的规则计算新容量并扩容。

  • 如果当前数组为空且不是默认的空数组,按一定的规则计算新容量并扩容。

  • 如果当前数组是默认的空数组,直接创建一个新数组。

先获取当前数组容量,判断当前数组是否需要扩容,如果需要,计算所需扩容量,创建新数组并赋值数据,如果不需要返回默认空数组

private Object[] grow(int minCapacity) {
    int oldCapacity = elementData.length;
    if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        int newCapacity = ArraysSupport.newLength(oldCapacity,
                minCapacity - oldCapacity, /* minimum growth */
                oldCapacity >> 1           /* preferred growth */);
        return elementData = Arrays.copyOf(elementData, newCapacity);
    } else {
        return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
    }
}

图解


标签:Object,Java,int,ArrayList,elementData,源码,数组,size
From: https://www.cnblogs.com/codyxz/p/18649631

相关文章