写点什么

ArrayList 源码解析

作者:前行
  • 2023-09-13
    广东
  • 本文字数:2217 字

    阅读完需:约 7 分钟

核心的属性

默认的初始化容量:private static final int DEFAULT_CAPACITY = 10;


空的数组实例:private static final Object[] EMPTY_ELEMENTDATA = {};


使用默认的容量大小空的数组实例:private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};


缓冲数组:transient Object[] elementData; 第一次使用才初始化


ArrayList 的大小:private int size;

构造器

ArrayList 提供了多个构造器


// 无参构造方法,初始容量10public 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); }}
// 通过集合初始化一个ArrayList// c不能为null,否则报 NPEpublic 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; }}
复制代码


数组拷贝


// java.util.Arrayspublic static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {    @SuppressWarnings("unchecked")    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;}
复制代码

存值方法 add()

public boolean add(E e) {    modCount++;    add(e, elementData, size);    return true;}

private void add(E e, Object[] elementData, int s) { if (s == elementData.length) elementData = grow(); elementData[s] = e; size = s + 1;}

public boolean addAll(Collection<? extends E> c) { Object[] a = c.toArray(); modCount++; int numNew = a.length; if (numNew == 0) return false; Object[] elementData; final int s; if (numNew > (elementData = this.elementData).length - (s = size)) elementData = grow(s + numNew); System.arraycopy(a, 0, elementData, s, numNew); size = s + numNew; return true;}
复制代码

扩容方法 grow()

private Object[] grow() {    return grow(size + 1);}
private Object[] grow(int minCapacity) { // 拷贝元素到新的数组中,底层调用的是 System.arraycopy方法 return elementData = Arrays.copyOf(elementData, newCapacity(minCapacity));}

// 计算新的容量: 1.5倍的上一次的容量private int newCapacity(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity <= 0) { // 无参构造器初始化 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) return Math.max(DEFAULT_CAPACITY, minCapacity); if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return minCapacity; } return (newCapacity - MAX_ARRAY_SIZE <= 0) ? newCapacity : hugeCapacity(minCapacity);}
复制代码

无参构造的扩容

@Testvoid debugArrayList() {    List<String> arrayList =  new ArrayList<>();    // 第一次扩容 size=10    arrayList.add("1");
for (int i = 2; i <= 10; i++) { arrayList.add(""+i); } // 第二次扩容 size=15 arrayList.add("11");
for (int i = 12; i <= 15; i++) { arrayList.add(""+i); } // 第二次扩容 size=22 arrayList.add("16");}
复制代码

指定初始容量的扩容

@Testvoid debugArrayListWithInitialCap() {    List<String> arrayList =  new ArrayList<>(20);    for (int i = 1; i <= 20; i++) {        arrayList.add("" + i);    }    // 第一次扩容, int newCapacity = oldCapacity + (oldCapacity >> 1);    // newCapacity =20+10=30    arrayList.add("21");
for (int i = 22; i <= 30; i++) { arrayList.add(""+i); } // 第二次扩容 size=30+15=45 arrayList.add("31");}
复制代码

取值方法 get()

public E get(int index) {    Objects.checkIndex(index, size);    return elementData(index);}
@SuppressWarnings("unchecked")E elementData(int index) { return (E) elementData[index];}
复制代码

经典错误

使用完 list 不做 clear

See Also

发布于: 刚刚阅读数: 5
用户头像

前行

关注

还未添加个人签名 2018-09-06 加入

还未添加个人简介

评论

发布
暂无评论
ArrayList源码解析_#java_前行_InfoQ写作社区