ArrayList就是一个数组结构

一、初始化

我们有三种初始化办法:无参数直接初始化、指定大小初始化、指定初始数据初始化。

  1. private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
  2. //无参数直接初始化,数组大小为空
  3. public ArrayList() {
  4. this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
  5. }
  6. //指定初始数据初始化
  7. public ArrayList(Collection<? extends E> c) {
  8. //elementData 是保存数组的容器,默认为 null
  9. elementData = c.toArray();
  10. //如果给定的集合(c)数据有值
  11. if ((size = elementData.length) != 0) {
  12. // c.toArray might (incorrectly) not return Object[] (see 6260652)
  13. //如果集合元素类型不是 Object 类型,我们会转成 Object
  14. if (elementData.getClass() != Object[].class) {
  15. elementData = Arrays.copyOf(elementData, size, Object[].class);
  16. }
  17. } else {
  18. // 给定集合(c)无值,则默认空数组
  19. this.elementData = EMPTY_ELEMENTDATA;
  20. }
  21. }

注意:ArrayList无参构造器初始化时,默认大小是空数组,并不是大家常说的10,10是在第一次add的时候扩容的数组值

二、新增和扩容实现

新增就是往数组中添加元素,主要分成两步:
1、判断是否要扩容,如果需要执行扩容操作
2、直接赋值

  1. public boolean add(E e) {
  2. //确保数组大小是否足够,不够执行扩容,size 为当前数组的大小
  3. ensureCapacityInternal(size + 1); // Increments modCount!!
  4. //直接赋值,线程不安全的
  5. elementData[size++] = e;
  6. return true;
  7. }
  8. private void ensureCapacityInternal(int minCapacity) {
  9. //如果初始化数组大小时,有给定初始值,以给定的大小为准,不走 if 逻辑
  10. if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
  11. minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
  12. }
  13. //确保容积足够
  14. ensureExplicitCapacity(minCapacity);
  15. }
  16. private void ensureExplicitCapacity(int minCapacity) {
  17. //记录数组被修改
  18. modCount++;
  19. // 如果我们期望的最小容量大于目前数组的长度,那么就扩容
  20. if (minCapacity - elementData.length > 0)
  21. grow(minCapacity);
  22. }
  23. //扩容,并把现有数据拷贝到新的数组里面去
  24. private void grow(int minCapacity) {
  25. int oldCapacity = elementData.length;
  26. // oldCapacity >> 1 是把 oldCapacity 除以 2 的意思
  27. int newCapacity = oldCapacity + (oldCapacity >> 1);
  28. // 如果扩容后的值 < 我们的期望值,扩容后的值就等于我们的期望值
  29. if (newCapacity - minCapacity < 0)
  30. newCapacity = minCapacity;
  31. // 如果扩容后的值 > jvm 所能分配的数组的最大值,那么就用 Integer 的最大值
  32. if (newCapacity - MAX_ARRAY_SIZE > 0)
  33. elementData = Arrays.copyOf(elementData, newCapacity);
  34. }

注意:
1、扩容的规则并不是翻倍,是原来容量大小+容量大小的一半,直白来说,就是扩容的大小是原来容量的1.5倍
2、ArrayList中的数组的最大值是Integer.MAX_VALUE,超过个值,JVM就不会给数组分配内存空间了
3、新增时,并没有对值进行严格的校验,所以ArrayList是允许null值的