ArrayList及同类比较

介绍

特性:元素可重复,容许null,查询效率高,插入和删除效率低,线程不安全;

主要用到下面两个方法:

Arrays.copyOf(T[] original, int newLength);根据newLength创建了一个新的数组,然后调用System.arraycopy()将原数组original内容复制到新数组中,并且将新数组返回;

System.arraycopy(Object src,int srcPos, Object dest,int destPos,int length);将一个数组的指定个数元素复制到另一个数组中;arrayCopy(arr1, 2, arr2, 5, 10) 意思是;将arr1数组里从索引为2的元素开始, 复制到数组arr2里的索引为5的位置, 复制的元素个数为10个.

添加方法:

add(E e),add(int index, E element),addAll();

add(E e):返回是否添加成功;

public boolean add(E e) {
	//检查容量,
    ensureCapacityInternal(size + 1);  // Increments modCount!!
	//给数组对应下标赋值
    elementData[size++] = e;
    return true;
}

private void ensureCapacityInternal(int minCapacity) {
	//是否为空数组
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }

    ensureExplicitCapacity(minCapacity);
}

private void ensureExplicitCapacity(int minCapacity) {
    modCount++;
	//当前容量是否够用,不够用,增加容量
    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
	//newCapacity为oldCapacity的1.5倍;
    int newCapacity = oldCapacity + (oldCapacity >> 1);
	//判断增加后容量和最小需要容量大小;
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
	//创建一个长度为newCapacity的新数组,并且将数组elementData的元素复制到新数组中,并且返回该数组,赋值给elementData;
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);
}

add(int index, E element):在指定下标添加元素;

public void add(int index, E element) {
	//检查下标是否越界
    if (index > size || index < 0)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
	//检查容量
    ensureCapacityInternal(size + 1);  // Increments modCount!!
	//腾位置,将当前数组从index开始的数据,复制到index+1开始的位置,复制个数为size-index;
    System.arraycopy(elementData, index, elementData, index + 1,
                     size - index);
	//给数组对应下标赋值;
    elementData[index] = element;
    size++;
}

addAll(Collection<? extends E> c)和addAll(int index, Collection<? extends E> c)分别和add(E e),add(int index, E element)对应;

插入的步骤

1:检查容量,如果需要扩容,调用Arrays.copyOf(),创建一个新数组,容量为newLength,并且调用System.arraycopy()将原数组中的元素复制到新数组;
2:腾位置,插入n个元素,插入位置index(不考虑尾部直接插入的情况下),先将当前数组从index开始的数据,复制到index+n开始的位置,依次对应;
3:插入,n=1,给数组对应下标赋值;n>1,将n个元素组成的数组,调用System.arraycopy() 复制到从index开始的位置;

由此可以看出,数组的插入效率低,时间复杂度为O(n)

get()和set()

get():判断下标是否越界,不越界,直接取出对应值;查询效率高。时间复杂度O(1),常数级别;

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

    return (E) elementData[index];
}

set(),效率也很高,时间复杂度O(1);

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;
}
删除

remove(int index):删除指定下标的元素;

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

    modCount++;
    E oldValue = (E) elementData[index];
	//需要移动元素的个数
    int numMoved = size - index - 1;
	//大于0,将下标index+1开始的numMoved个元素,移动到下标index位置上;
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    elementData[--size] = null; // clear to let GC do its work

    return oldValue;
}

remove(Object o):删除指定元素;先找到数组中最先出现相同元素的下标;再根据下标删除;

public boolean remove(Object o) {
    if (o == null) {
        for (int index = 0; index < size; index++)
            if (elementData[index] == null) {
                fastRemove(index);
                return true;
            }
    } else {
        for (int index = 0; index < size; index++)
            if (o.equals(elementData[index])) {
                fastRemove(index);
                return true;
            }
    }
    return false;
}

//和remove(int index)相同
private void fastRemove(int index) {
    modCount++;
    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
}

removeAll():从数组elementData中 删除c包含的数组elementData的元素;

public boolean removeAll(Collection<?> c) {
	//非空判断
    Objects.requireNonNull(c);
    return batchRemove(c, false);
}

private boolean batchRemove(Collection<?> c, boolean complement) {
    final Object[] elementData = this.elementData;
    int r = 0, w = 0;
    boolean modified = false;
    try {
		//遍历数组
        for (; r < size; r++)
			//c中不包含elementData的元素,重新放入到数组elementData中
            if (c.contains(elementData[r]) == complement)
                elementData[w++] = elementData[r];
    } finally {
        // Preserve behavioral compatibility with AbstractCollection,
        // even if c.contains() throws.
		//出现异常
        if (r != size) {
            System.arraycopy(elementData, r,
                             elementData, w,
                             size - r);
            w += size - r;
        }
		//说明c中只包含数组elementData中部分元素;
        if (w != size) {
			//清除空间,赋值为null;
            // clear to let GC do its work
            for (int i = w; i < size; i++)
                elementData[i] = null;
            modCount += size - w;
            size = w;
            modified = true;
        }
    }
    return modified;
}

迭代器(Iterator):在迭代过程中可以删除元素;

hasNext:判断游标cursor右侧是否还有元素;判断cursor是否小于size;
next():返回游标cursor对应的数据,并将游标cursor+1remove():删除游标cursor右侧的数据;在执行完next()方法之后,只能执行一次,否则会报错;
比较

ArrayList:元素可重复,容许null,查询效率高,插入和删除效率低,线程不安全;

Vector:线程安全,(增删改查)都是synchronized方法,效率低,其他和ArrayList一致;都是以数组作为底层;

CopyOnWriteArrayList:是concurrent包中的,和Vector类似,线程安全,(增删改)用的同步代码块,查操作异步的,不继承AbstractList;其他操作一样;没有缓冲区,在对其实例进行修改操作(add/remove等)会新建一个数据并修改,修改完毕之后,再将原来的引用指向新的数组,也就没有了ConcurrentModificationException错误。可以边循环,别做其他操作; 适用于读操作频繁;

Stack(栈):是Vector的子类,也是线程安全的;同时还具有LIFO(后进先出);push()入栈(添加一个元素);
主要方法:peek()获取栈顶的元素值;pop()出栈(从栈顶删除该元素),并且返回该值;search():判断栈中是否存在该元素,返回距离栈顶最近的距离;

如有问题请多指教,谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值