【无标题】

ArrayList

总结
(1)ArrayList内部使用数组存储元素,当数组长度不够时进行扩容,每次加一半的空间,ArrayList不会进行缩容;
(2)ArrayList支持随机访问,通过索引访问元素极快,时间复杂度为O(1);
(3)ArrayList添加元素到尾部极快,平均时间复杂度为O(1);
(4)ArrayList添加元素到中间比较慢,因为要搬移元素,平均时间复杂度为O(n);
(5)ArrayList从尾部删除元素极快,时间复杂度为O(1);
(6)ArrayList从中间删除元素比较慢,因为要搬移元素,平均时间复杂度为O(n);
(7)ArrayList支持求并集,调用addAll(Collection c)方法即可;
(8)ArrayList支持求交集,调用retainAll(Collection c)方法即可;
(7)ArrayList支持求单向差集,调用removeAll(Collection c)方法即可;

构造函数:

public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else {
            if (initialCapacity != 0) {  //传入初始容量小于零时
                throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
            }
            this.elementData = EMPTY_ELEMENTDATA;  // 等于零时,空对象数组
        }
    }
    
public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;  //如果没有传入初始容量,则使用空数组DEFAULTCAPACITY_EMPTY_ELEMENTDATA
    }
    
// 把传入集合的元素初始化到ArrayList中
public ArrayList(Collection<? extends E> c) {
        this.elementData = c.toArray();  // 集合转数组
        if ((this.size = this.elementData.length) != 0) {
        	// 检查c.toArray()返回的是不是Object[]类型,如果不是,重新拷贝成Object[].class类型
            if (this.elementData.getClass() != Object[].class) {
                this.elementData = Arrays.copyOf(this.elementData, this.size, Object[].class);
            }
        } else {
            this.elementData = EMPTY_ELEMENTDATA;  // // 如果c的空集合,则初始化为空数组EMPTY_ELEMENTDATA
        }
    }

add(E e)方法
添加元素到末尾,平均时间复杂度为O(1)。

public boolean add(E e) {
        ++this.modCount;
        this.add(e, this.elementData, this.size);
        return true;
    }
private void add(E e, Object[] elementData, int s) {
        if (s == elementData.length) {
            elementData = this.grow();  //扩容
        }
        elementData[s] = e;
        this.size = s + 1;
    }
private Object[] grow() {
        return this.grow(this.size + 1);
    }
private Object[] grow(int minCapacity) {
		// 创建新容量的数组并把老数组拷贝到新数组
        return this.elementData = Arrays.copyOf(this.elementData, this.newCapacity(minCapacity));
    }
 private int newCapacity(int minCapacity) {
        int oldCapacity = this.elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);  //1.5倍扩容
        if (newCapacity - minCapacity <= 0) {
            if (this.elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
                return Math.max(10, minCapacity);  // 初始10,或用于addAll中,用来选择相符合的容量
            } else if (minCapacity < 0) {
                throw new OutOfMemoryError();
            } else {
                return minCapacity;
            }
        } else {
            return newCapacity - 2147483639 <= 0 ? newCapacity : hugeCapacity(minCapacity);
        }
    }

add(int index, E element)方法
添加元素到指定位置,平均时间复杂度为O(n)。

public void add(int index, E element) {
		// 检查是否越界
        this.rangeCheckForAdd(index);
        ++this.modCount;
        int s;
        Object[] elementData;
        if ((s = this.size) == (elementData = this.elementData).length) {
            elementData = this.grow();  // 扩容
        }
		// 把插入索引位置后的元素都往后挪一位,在插入索引位置放置插入的元素;
        System.arraycopy(elementData, index, elementData, index + 1, s - index);
        elementData[index] = element;
        this.size = s + 1;
    }

addAll(Collection c)方法
求两个集合的并集

public boolean addAll(Collection<? extends E> c) {
        Object[] a = c.toArray();
        ++this.modCount;
        int numNew = a.length;
        if (numNew == 0) {
            return false;
        } else {
            Object[] elementData;
            int s;
            if (numNew > (elementData = this.elementData).length - (s = this.size)) {
                elementData = this.grow(s + numNew);
            }
            // 把数组a中的元素拷贝到elementData的尾部;
            System.arraycopy(a, 0, elementData, s, numNew);
            this.size = s + numNew;
            return true;
        }
    }

remove(int index)方法
删除指定索引位置的元素,时间复杂度为O(n)。
如果删除的不是最后一位,则其它元素往前移一位;将最后一位置为null,方便GC回收;
可以看到,ArrayList删除元素的时候并没有缩容。

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

remove(Object o)方法
删除指定元素值的元素,时间复杂度为O(n)。
找到第一个等于指定元素值的元素;快速删除;
fastRemove(int index)相对于remove(int index)少了检查索引越界的操作,可见jdk将性能优化到极致。

public boolean remove(Object o) {
        Object[] es = this.elementData;
        int size = this.size;
        int i = 0;
        if (o == null) {
            while(true) {
                if (i >= size) {
                    return false;
                }
                if (es[i] == null) {
                    break;
                }
                ++i;
            }
        } else {
            while(true) {
                if (i >= size) {
                    return false;
                }
                if (o.equals(es[i])) {
                    break;
                }
                ++i;
            }
        }

        this.fastRemove(es, i);
        return true;
    }

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值