鸟枪换炮读源码系列之ArrayList(java11)

经常用到ArrayList,知道和LinkedList的对比优缺点,但是没那么读过源码。
首先它继承了AbstractList,实现了List接口,RandomAccess接口(支持快速随机访问,查询快的标记接口),Cloneable接口,序列化接口。
初始化参数:

// 初始容量为10
 private static final int DEFAULT_CAPACITY = 10;
 // 空数组实例
 private static final Object[] EMPTY_ELEMENTDATA = {};
 //	默认空数组实例,区别于上面的就是第一个元素添加时候增长多少
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
// 存储数组缓冲区,ArrayList的容量就是此数组的长度,第一个元素添加的时候,数组容量从0变10
 transient Object[] elementData;
 // 大小
  private int size;
  // ArrayList被修改的次数,初始值为0,来自父类
   protected transient int modCount = 0;
   //  最大容量,为2的31次方-1 ,再减8,除非有必要再使用,否则可能有些jvm会OutOfMemoryError报错
   private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

三个构造函数,不带参数,带容量大小参数,带集合参数:

// 创建指定容量的ArrayList
public ArrayList(int initialCapacity) {
       if (initialCapacity > 0) {
       // 指定容量大于0,那么创建一个Object[initialCapacity]的数组
           this.elementData = new Object[initialCapacity];
       } else if (initialCapacity == 0) {
       // 指定容量小于0,那么等于空数组实例
           this.elementData = EMPTY_ELEMENTDATA;
       } else {
       //	指定容量小于0,抛出异常 : IllegalArgumentException
           throw new IllegalArgumentException("Illegal Capacity: "+
                                              initialCapacity);
       }
   }
   // 不带参数的构造函数,创建一个容量为10的ArrayList
    public ArrayList() {
       this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
   }
   // 参数为集合的构造函数,顺序为集合迭代器返回顺序
    public ArrayList(Collection<? extends E> c) {
    	// 集合转换为数组
       elementData = c.toArray();
       //	如果数组大小不为0
       if ((size = elementData.length) != 0) {
          // 防止没有返回对象数组的错误
           if (elementData.getClass() != Object[].class)
           	// 元素拷贝创建ArrayList
               elementData = Arrays.copyOf(elementData, size, Object[].class);
       } else {
           // 否则创建一个空ArrayList
           this.elementData = EMPTY_ELEMENTDATA;
       }
   }

trimToSize()方法:压缩容量到实际大小

public void trimToSize() {
		// 修改次数+1
       modCount++;
       //	如果真实大小小于容量
       if (size < elementData.length) {
       	//	当大小等于0时候为空数组
           elementData = (size == 0)
             ? EMPTY_ELEMENTDATA
             // 当大小不等于0的时候复制真实数组
             : Arrays.copyOf(elementData, size);
       }
   }

确保容量方法ensureCapacity(int minCapacity)

public void ensureCapacity(int minCapacity) {
	// 如果参数minCapacity大于真实长度
       if (minCapacity > elementData.length
           && !(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
                && minCapacity <= DEFAULT_CAPACITY)) {
                // 增加修改次数
           modCount++;
           // 扩容
           grow(minCapacity);
       }
   }
   // 扩容成新的大小数组
private Object[] grow(int minCapacity) {
       return elementData = Arrays.copyOf(elementData,
                                          newCapacity(minCapacity));
   }
   // 计算新容量方法
private int newCapacity(int minCapacity) {
   	// 老容量为真实长度
       int oldCapacity = elementData.length;
       // 新容量为老容量*1.5
       int newCapacity = oldCapacity + (oldCapacity >> 1); 
       // 如果新容量小于minCapacity,则返回minCapacity
       if (newCapacity - minCapacity <= 0) {
           if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
               return Math.max(DEFAULT_CAPACITY, minCapacity);
           if (minCapacity < 0) // overflow
               throw new OutOfMemoryError();
           return minCapacity;
       }
       // 无参增长新容量
   private Object[] grow() {
       return grow(size + 1);
   }
       // 判断是否大于最大容量,小于的话返回新容量,大于的话直接返回最大容量
       return (newCapacity - MAX_ARRAY_SIZE <= 0)
           ? newCapacity
           : hugeCapacity(minCapacity);
   }
   // 创建最大容量的静态方法
private static int hugeCapacity(int minCapacity) {
       if (minCapacity < 0) // overflow
           throw new OutOfMemoryError();
       return (minCapacity > MAX_ARRAY_SIZE)
           ? Integer.MAX_VALUE
           : MAX_ARRAY_SIZE;
   }

size() 方法返回size

public int size() {
        return size;
    }

isEmpty() 方法返回是否为空

public boolean isEmpty() {
        return size == 0;
    }

contains(Object o) 方法返回是否包含某个对象

public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }

indexOf(Object o) 方法返回第一个找到该对象的index,如果找不到 返回-1

public int indexOf(Object o) {
	//	从0位找到最后位
       return indexOfRange(o, 0, size);
   }
   // 找到对象从start到end之间的index,遍历数组
   int indexOfRange(Object o, int start, int end) {
       Object[] es = elementData;
       if (o == null) {
           for (int i = start; i < end; i++) {
               if (es[i] == null) {
                   return i;
               }
           }
       } else {
           for (int i = start; i < end; i++) {
           // 判断两个值是否相等,相等返回
               if (o.equals(es[i])) {
                   return i;
               }
           }
       }
       return -1;
   }

lastIndexOf(Object o) 方法,找到最后一个该对象的index,没有则-1

// 同上,从尾部开始遍历,返回
public int lastIndexOf(Object o) {
       return lastIndexOfRange(o, 0, size);
   }

   int lastIndexOfRange(Object o, int start, int end) {
       Object[] es = elementData;
       if (o == null) {
           for (int i = end - 1; i >= start; i--) {
               if (es[i] == null) {
                   return i;
               }
           }
       } else {
           for (int i = end - 1; i >= start; i--) {
               if (o.equals(es[i])) {
                   return i;
               }
           }
       }
       return -1;
   }

clone() 方法,返回一个浅拷贝,元素本身不会被复制

 public Object clone() {
      try {
          ArrayList<?> v = (ArrayList<?>) super.clone();
          // 调用Arrays中的copyOf方法
          v.elementData = Arrays.copyOf(elementData, size);
          v.modCount = 0;
          return v;
      } catch (CloneNotSupportedException e) {
          throw new InternalError(e);
      }
  }
  // 以下为Arrays中的方法
public static <T> T[] copyOf(T[] original, int newLength) {
      return (T[]) copyOf(original, newLength, original.getClass());
  }
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
      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;
  }
  //以下为System中的arraycopy方法
    public static native void arraycopy(Object src,  int  srcPos,
                                      Object dest, int destPos,
                                      int length);

toArray()方法,返回一个包含所有元素的数组

public Object[] toArray() {
      return Arrays.copyOf(elementData, size);
  }
public <T> T[] toArray(T[] a) {
      if (a.length < size)
          // Make a new array of a's runtime type, but my contents:
          return (T[]) Arrays.copyOf(elementData, size, a.getClass());
      System.arraycopy(elementData, 0, a, 0, size);
      if (a.length > size)
          a[size] = null;
      return a;
  }

get(int index)方法,返回index元素

 public E get(int index) {
      Objects.checkIndex(index, size);
      return elementData(index);
  }
   E elementData(int index) {
      return (E) elementData[index];
  }
  // 以下为Objects的方法,检查index是否在范围内
  public static int checkIndex(int index, int length) {
      return Preconditions.checkIndex(index, length, null);
  }
  //以下为Preconditions的方法,如果index在范围外则抛出outOfBoundsCheckIndex异常
  public static <X extends RuntimeException>
  int checkIndex(int index, int length,
                 BiFunction<String, List<Integer>, X> oobef) {
      if (index < 0 || index >= length)
          throw outOfBoundsCheckIndex(oobef, index, length);
      return index;
  }

set(int index, E element)方法,修改指定index处的值,并返回旧值

public E set(int index, E element) {
	// 检查index范围
      Objects.checkIndex(index, size);
    // 得到旧值
      E oldValue = elementData(index);
      // 更换新值
      elementData[index] = element;
      // 返回旧值
      return oldValue;
  }

add(E e) 方法,在list末尾加上e,返回boolean

 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;
  }  

add(int index, E element)方法,指定index位置插入值,并且当前和之后受影响元素后移,无返回值

public void add(int index, E element) {
	// 检查index是否在范围内,不在的话抛出IndexOutOfBoundsException异常
      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;
  }
  private void rangeCheckForAdd(int index) {
      if (index > size || index < 0)
          throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
  }

remove(int index)方法,返回被移除对象

    public E remove(int index) {
          Objects.checkIndex(index, size);
          final Object[] es = elementData;
          E oldValue = (E) es[index];
          fastRemove(es, index);
          return oldValue;
      }
      private void fastRemove(Object[] es, int i) {
      modCount++;
      final int newSize;
      if ((newSize = size - 1) > i)
          System.arraycopy(es, i + 1, es, i, newSize - i);
      es[size = newSize] = null;
  }

很多操作中都会出现的System.arraycopy数组复制方法,是一种native的方法

 public static native void arraycopy(Object src,  int  srcPos,
                                      Object dest, int destPos,
                                      int length);

参数
src: 原始数组
srcPos:原始数组的起始位置
dest: 目标数组
destPos: 目标数组的起始位置
length: 复制元素的数量

clear()方法,清空,无返回值,循环设置null,size设为0

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

addAll(Collection<? extends E> c) 方法,添加集合,返回boolean

 public boolean addAll(Collection<? extends E> c) {
 // 首先集合转对数组
      Object[] a = c.toArray();
      // 增加修改次数
      modCount++;
      // 获得对象数组长度
      int numNew = a.length;
      // 长度为0返回false
      if (numNew == 0)
          return false;
      Object[] elementData;
      final int s;
      // 如果新增容量大于ArrayList的剩余容量则进行扩容
      if (numNew > (elementData = this.elementData).length - (s = size))
          elementData = grow(s + numNew);
        // 复制对象数组到ArrayList中
      System.arraycopy(a, 0, elementData, s, numNew);
      size = s + numNew;
      return true;
  }

addAll(int index, Collection<? extends E> c) 增加集合到数组中,从index开始,返回值为boolean,具体操作和上面差不多,只是起始位置,复制个数修改一下

public boolean addAll(int index, Collection<? extends E> c) {
        rangeCheckForAdd(index);

        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);

        int numMoved = s - index;
        if (numMoved > 0)
            System.arraycopy(elementData, index,
                             elementData, index + numNew,
                             numMoved);
        System.arraycopy(a, 0, elementData, index, numNew);
        size = s + numNew;
        return true;
    }

void removeRange(int fromIndex, int toIndex)方法,移除fromIndex和toIndex之间的元素,包括fromIndex但是不包括toIndex

protected void removeRange(int fromIndex, int toIndex) {
		// 判断参数是否正确
        if (fromIndex > toIndex) {
            throw new IndexOutOfBoundsException(
                    outOfBoundsMsg(fromIndex, toIndex));
        }
        // 增加修改次数
        modCount++;
        // 内部方法移除
        shiftTailOverGap(elementData, fromIndex, toIndex);
    }
    private void shiftTailOverGap(Object[] es, int lo, int hi) {
    // 从toIndex开始之后的数组,移动到fromIndex位置开始
        System.arraycopy(es, hi, es, lo, size - hi);
        // 把容量之外的元素变成null
        for (int to = size, i = (size -= hi - lo); i < to; i++)
            es[i] = null;
    }

boolean removeAll(Collection<?> c) 方法,移除ArrayList中所有c中的元素

public boolean removeAll(Collection<?> c) {
        return batchRemove(c, false, 0, size);
    }
 boolean batchRemove(Collection<?> c, boolean complement,
                        final int from, final int end) {
         // 检查不为null
        Objects.requireNonNull(c);
        final Object[] es = elementData;
        int r;
        // 如果c中不包含ArrayList中的元素,那么直接返回false,否则向下执行,			同时r定位到第一个包含的位置
        for (r = from;; r++) {
            if (r == end)
                return false;
            if (c.contains(es[r]) != complement)
                break;
        }
        // w定位到r下一个位置
        int w = r++;
        try {
            for (Object e; r < end; r++)
                if (c.contains(e = es[r]) == complement)
                // 利用w指针记录如果c中包含的元素,那么就删除
                    es[w++] = e;
        } catch (Throwable ex) {
            System.arraycopy(es, r, es, w, end - r);
            w += end - r;
            throw ex;
        } finally {
            modCount += end - w;
            // 移除w和end之间的元素
            shiftTailOverGap(es, w, end);
        }
        return true;
    }
    // Objects中如果对象参数为null则抛出异常的方法
     public static <T> T requireNonNull(T obj) {
        if (obj == null)
            throw new NullPointerException();
        return obj;
    }

ListIterator listIterator(int index)方法,返回一个list iterator, 从index处开始。

public ListIterator<E> listIterator(int index) {
       rangeCheckForAdd(index);
       return new ListItr(index);
   }

List subList(int fromIndex, int toIndex) 方法返回一个范围内的子类

public List<E> subList(int fromIndex, int toIndex) {
        subListRangeCheck(fromIndex, toIndex, size);
        return new SubList<>(this, fromIndex, toIndex);
    }

void writeObject(java.io.ObjectOutputStream s) 方法,序列化

private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException {
        // Write out element count, and any hidden stuff
        int expectedModCount = modCount;
        s.defaultWriteObject();

        // Write out size as capacity for behavioral compatibility with clone()
        s.writeInt(size);

        // Write out all elements in the proper order.
        for (int i=0; i<size; i++) {
            s.writeObject(elementData[i]);
        }

        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
    }

void readObject(java.io.ObjectInputStream s)方法,反序列化

private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {

        // Read in size, and any hidden stuff
        s.defaultReadObject();

        // Read in capacity
        s.readInt(); // ignored

        if (size > 0) {
            // like clone(), allocate array based upon size not capacity
            SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Object[].class, size);
            Object[] elements = new Object[size];

            // Read in all elements in the proper order.
            for (int i = 0; i < size; i++) {
                elements[i] = s.readObject();
            }

            elementData = elements;
        } else if (size == 0) {
            elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new java.io.InvalidObjectException("Invalid size: " + size);
        }
    }

ArrayList中包含了四个内部类

 private class Itr implements Iterator<E> 
 private class ListItr extends Itr implements ListIterator<E>
 private static class SubList<E> extends AbstractList<E> implements RandomAccess
 final class ArrayListSpliterator implements Spliterator<E>

更详细内容可以参考:link

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值