ArrayList jdk1.8基础和源码分析


ArrayList是基于数组实现的列表,数组的物理存储空间连续,修改和查看的复杂度为O(1),添加和删除需要更多操作。

ArrayList()构造函数

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
 	//默认初始容量为10
    private static final int DEFAULT_CAPACITY = 10;

    private static final Object[] EMPTY_ELEMENTDATA = {};

    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
	// 
    transient Object[] elementData; 
	//下一个需要存入数据的下标,从0开始
    private int size;

//指定初始容量,如果initialCapacity > 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);
        }
    }

//默认是个空数组
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

//指定elementData和elementData的size
    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;
        }
    }
//Arrays.copyOf
public 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;
    }
//System.arraycopy
public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);

add(E element) 列表尾部添加元素

进行是否需要扩容的判断

  • add(E e) 在数组的末端添加对象

  • add(int index, E element) 在指定的索引位置上添加对象,需要对index后的所有对象往后移动一位

//在数组的末端添加对象
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e; 
        return true;
    }

//在指定的索引位置上添加对象
    public void add(int index, E element) {
        if (index > size || index < 0)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        System.arraycopy(elementData, index, elementData, index + 1, size - index);
        elementData[index] = element;
        size++;
    }
    
    //
     private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        	//取DEFAULT_CAPACITY和minCapacity中的最大值
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); 
        }
        ensureExplicitCapacity(minCapacity);
    }

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;
        if (minCapacity - elementData.length > 0)
            grow(minCapacity); //如果数组大小,小于需要的最小容量,则扩容
    }

remove(index) 删除指定索引的元素

索引判断,是否数组越界

取出elementData[index], 并最终返回oldValue

如果不是移除最后一个对象,需要对index+1之前的所有对象往前移一位

移除后,elementData[–size]=null 清除引用

 public E remove(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
            
        modCount++;
        E oldValue = (E) elementData[index];
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index, numMoved);
        elementData[--size] = null; // clear to let GC do its work
        return oldValue;
    }

set(index, element) 修改指定索引的元素为element

索引判断,是否数组越界

给elementData[index]重新赋值,并返回oldValue

public E set(int index, E element) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));

        E oldValue = (E) elementData[index];
        elementData[index] = element;
        return oldValue;
    }

get(index) 查找指定索引的元素

索引判断,是否数组越界

取出elementData[index]并返回

  public E get(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));

        return (E) elementData[index];
    }

grow() 扩容

minCapacity取的是DEFAULT_CAPACITY (10)和minCapacity (size + 1)中的最大值

newCapacity = 1.5倍oldCapacity, oldCapacity是elementData.length,扩容原来的1/2倍

如果newCapacity > MAX_ARRAY_SIZE,如果minCapacity > MAX_ARRAY_SIZE, newCapactiy取Integer.MAX_VALUE,否则取MAX_ARRAY_SIZE

 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
 
 private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1); //尝试扩容为原来的1.5倍
        if (newCapacity - minCapacity < 0) //如果1.5倍还不满足需求,直接赋值为minCapacity
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0) //如果minCapacity > (Integer.MAX_VALUE - 8),则...
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity); //正式扩容
    }

    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() 存储元素的总值

返回的是列表包含的对象个数,而不是elementData.length, size小于等于elementData.length,size+1如果大于elementData.length,就需要扩容啦!

 public int size() {
        return size;
 }

isEmpty() 是否是空列表

同上,如果size==0,则列表里没有任何对象。add()会进行size++,remove()会进行size–。

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

contains(Object) 是否包含对象o

get(index)可以通过索引得到相应的value,indexOf(Object)可以根据value返回索引。

indexOf(Object)返回的索引>0,则列表里存在value,否则不存在

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

    public int indexOf(Object o) {
        if (o == null) { //遍历匹配
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else { //遍历匹配
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

总结

  • ArrayList是基于数组实现的列表,数组的物理存储空间连续,修改和查看的复杂度为O(1),添加和删除需要更多操作。

  • 根据下标索引进行定位,所以set和get方便;add和remove需要进行批量移动。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值