ArrayList集合(基于jdk11)

ArrayList集合(基于jdk11)


简介

Arraylist 是一个有序的数组集合,继承了AbstractList类,实现了List接口、RandomAccess接口、Cloneable接口和Serializable接口。

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{...}
  • List:提供List基本方法,同时让ArrayList有集合的方法以及行为属性。
  • RandomAccess:该实现类支持随机访问,也就是下标访问 get(index)。
  • Cloneable:该类是克隆的接口。不仅仅实现了浅拷贝,也可以重写该类去实现深拷贝。
/**
浅拷贝:
基本数据类型的变量拷贝之后是独立的,不会随着源变量变动而变
String类型拷贝之后也是独立的
引用类型拷贝的是引用地址,拷贝前后的变量引用同一个堆中的对象。
*/
/**
深拷贝:
变量的所有引用类型变量(除了String)都需要实现Cloneable(数组可以直接调用clone方法),clone方法中,引用类型需要各自去重写该方法实现深拷贝
*/
  • java.io.Serializable:该类是序列化接口。

基本属性

//序列化版本号:类内容的改变会影响版本号变化,导致反序列化失败(自动生成或自己定义)
private static final long serialVersionUID = 8683452581122892189L;

//如果实例化时未指定容量,则在初次添加元素时会进行扩容使用此容量作为数组长度
private static final int DEFAULT_CAPACITY = 10;

//一个空由于某些操作导致数据变成空的数组
private static final Object[] EMPTY_ELEMENTDATA = {};

//利用无参构造器,无论创建多少个默认的ArrayList,只要不添加元素都会指向这个空数组节省空间
//它和上面就是该数组再次添加元素会自动扩容10
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

// ArrayList存储数据的地方  transient 是禁止序列化
transient Object[] elementData; // non-private to simplify nested class access

//ArrayList中的元素个数
private int size;

构造方法

/*
	把DEFAULTCAPACITY_EMPTY_ELEMENTDATA赋值给elementData
	第一次添加元素时容量扩大至 10 的。
	*/
	ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
    
    /*
	当 initialCapacity 为零时则是把 EMPTY_ELEMENTDATA 赋值给 elementData。 
	当 initialCapacity 大于零时初始化一个大小为 initialCapacity 
	的 object 数组并赋值给 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);
        }
    }
    
    /*
	将collection转换成数组,存储在elementData
	if c.toArray成object[]失败用Arrays.copyOf将elementData存储数据
	转换成object[]对象拷贝到elementData中
	*/
    //ArrayList(Collection<? extends E> c)
    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;
        }
    }

基本操作

//获取长度
public int size() {
    return size;
}
//判断长度是否为0(未做非空判断)
public boolean isEmpty() {
    return size == 0;
}
//判断是否包含,
public boolean contains(Object o) {
    return indexOf(o) >= 0;
}
//获取对象最早出现的索引,ArrayList是可重复存储相同的对象,没有该对象返回-1
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是可重复存储相同的对象,没有该对象返回-1
public int lastIndexOf(Object o) {
    if (o == null) {
        for (int i = size-1; i >= 0; i--)
            if (elementData[i]==null)
                return i;
    } else {
        for (int i = size-1; i >= 0; i--)
            if (o.equals(elementData[i]))
                return i;
    }
    return -1;
}

//重写的clone方法
public Object clone() {
    try {
        ArrayList<?> v = (ArrayList<?>) super.clone();
        v.elementData = Arrays.copyOf(elementData, size);
        v.modCount = 0;
        return v;
    } catch (CloneNotSupportedException e) {
        throw new InternalError(e);
    }
}

public Object[] toArray() {
    return Arrays.copyOf(elementData, size);
}

//把ArrayList数组中的空位置给减掉了
public void trimToSize() {
    modCount++;
    if (size < elementData.length) {
        elementData = (size == 0)
            ? EMPTY_ELEMENTDATA
            : Arrays.copyOf(elementData, size);
    }
}

添加元素

ArrayList arr = new ArrayList();
arr.add(1);
//size大小是1,而elementData大小是默认初始化大小10
//默认最大的数组长度
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
//最大的int数
public static final int MAX_VALUE = 0x7fffffff;

//往集合中add元素
public boolean add(E e) {
    //操作数++
    modCount++;
    add(e, elementData, size);
    return true;
}

//集合元素数量=elementData的长度时扩容,再将元素赋值到索引为s的位置
private void add(E e, Object[] elementData, int s) {
    if (s == elementData.length)
        elementData = grow();
    elementData[s] = e;
    size = s + 1;
}

//扩容
private Object[] grow() {
    return grow(size + 1);
}

//复制之前的数组扩容后赋值到新的数组  minCapacity扩容后最小的值
private Object[] grow(int minCapacity) {
    return elementData = Arrays.copyOf(elementData, newCapacity(minCapacity));
}

//计算扩容后数组的长度
private int newCapacity(int minCapacity) {
    // overflow-conscious code
    //旧的数组长度
    int oldCapacity = elementData.length;
    //新的数组长度 i >> 1 (可以理解为除以2) 新的数组长度为旧的数组长度的1.5倍
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    //如果新的数组长度小于于扩容后需要的最小的数组长度
    if (newCapacity - minCapacity <= 0) {
        //判断是不是初始空数组,如果是反回默认长度
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        //如果最小值小于0,抛出错误 OutOfMemoryError();
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        //返回扩容需要最小的长度
        return minCapacity;
    }
    //如果新的数组长度小于最大的数组长度,则返回新的数组长度
    return (newCapacity - MAX_ARRAY_SIZE <= 0)
        ? newCapacity
        : hugeCapacity(minCapacity);
}

//当新的的数组长度大于默认最大的数组长度时执行
private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
    //需要的长度大于默认最大的数组长度,则返回最大的int数,否则返回最大的数组长度
    return (minCapacity > MAX_ARRAY_SIZE)
        ? Integer.MAX_VALUE
        : MAX_ARRAY_SIZE;
}

指定下标添加元素

public void add(int index, E element) {
    //判断是否索引越界
    rangeCheckForAdd(index);
    modCount++;
    final int s;
    Object[] elementData;
    //判断是否需要扩容,记录操作数
    if ((s = size) == (elementData = this.elementData).length)
        elementData = grow();
    //讲index位置之后的元素向后移动1个位置  
    System.arraycopy(elementData, index,
                     elementData, index + 1,
                     s - index);
    //在index位置添加元素
    elementData[index] = element;
    size = s + 1;
}

//判断是否索引越界
private void rangeCheckForAdd(int index) {
    if (index > size || index < 0)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

删除元素

//根据索引删除
public E remove(int index) {
    Objects.checkIndex(index, size);
    final Object[] es = elementData;

    @SuppressWarnings("unchecked") 
    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;
}

总结

  1. ArrayList 是支持快速访问、复制、序列化的。
  2. ArrayList 的插入是尾插法。
  3. 想要提升ArrayList的大批量插入速度,我们可以减少扩容操作,给一个大的初始值进行创建ArrayList,这样做能够使得ArrayList的大批量插入元素速度变得非常快。
  4. Arraylist并非线程安全的。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值