ArrayList 学习



底层实现:ArrayList的底层是一个数组,默认的数组长度为10
线程安全:ArrayList是线程不安全的
优点: ArrayList基于数组,所以擅长读取,在末尾add值也很快捷
缺点: 在指定下标add值的性能较差

ArrayList 默认值

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;

所有的数据都存储在elementData中

ArrayList的构造器

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

 public ArrayList() {
     this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
 }

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

ArrayList有三个构造器:
(1)带有 initialCapacity 的构造器,如果我们可以确认生成的ArrayList的长度,建议创建ArrayList对象的时候带上初始化的容量值,避免内存空间的浪费
(2)无参的构造器,无参的构造器会使用DEFAULTCAPACITY_EMPTY_ELEMENTDATA,使用DEFAULTCAPACITY_EMPTY_ELEMENTDATA是为了在第一次加入值的时候计算应该扩充多大的ArrayList长度
(3)带有初始化Collection的构造器。会将size设置为Collection的长度,并使用Arrays.copyOf()方法将Collection的内容赋给elementData

添加一个元素

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}


public void add(int index, E element) {
    rangeCheckForAdd(index);

    ensureCapacityInternal(size + 1);  // Increments modCount!!
    System.arraycopy(elementData, index, elementData, index + 1,
                     size - index);
    elementData[index] = element;
    size++;
}

有两种添加元素的方式
(1): 直接添加到末尾
(2): 在指定下标处添加,需要先判断下标是否正确,同时需要将该下标之后的值都做相应的移位,会导致性能的降低
但无论何种方式,都需要先做ensureCapacityInternal() 判断,用于判断ArrayList对象的长度是否需要进行扩容

ensureCapacityInternal(size + 1)的过程
如果当前elementData的长度 已经无法满足 size+1的范围,则会进行扩容
扩容的大小为当前长度的1/2 + 1
如果这个长度仍无法满足size+1的要求,则ArrayList的长度会直接被设置为 size+1
代码如下:

private void grow(int minCapacity) {
   // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);
}

在扩容之后,如果ArrayList的长度大于Integer.MAX_VALUE - 8, 那么长度则直接设置为 Integer.MAX_VALUE

这意味着ArrayList的所能添加的值的最大个数为 Integer.MAX_VALUE.

获取一个元素

public E get(int index) {
    rangeCheck(index);

    return elementData(index);
}

先需要判断下标是否正确,然后直接返回该下标对于的数组的值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值