ArrayList源码之删除和获取元素的方法


前言

本文主要编写ArrayList源码关于remove()方法及get()方法。
关于ArrayList源码的初始化化及add()方法源码可以看看我这篇文章: ArrayList新增元素源码分析


一、ArrayList中的删除方法

1、remove(Object o)

输入一个元素,将数组中第一个这个元素·删掉
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;
    }

通过源码我们可以看出这段代码逻辑很简单,就是一个简单的遍历对象数组elementData,比较值,如果相同进行删除操作

fastRemove(int index)源码部分:

private void fastRemove(int index) {
		//记录集合被修改次数
        modCount++;
        //需要移动的长度
        int numMoved = size - index - 1;
        if (numMoved > 0)
        //如果删除的不是最后一个元素,将删除的元素到最后的元素整块前移
            System.arraycopy(elementData, index+1,
             elementData, index, numMoved);
         //将最后对象数组最后一个元素设置为空,在下一次gc时回收空间
        elementData[--size] = null; // clear to let GC do its work
    }

2、E remove(int index)

传入一个下标,将该下标中的元素删除
E remove(int index)源码:

public E remove(int index) {
		//判断index是否合法
        rangeCheck(index);

		//操作次数+1
        modCount++;
        //获得需要删除的元素
        E oldValue = elementData(index);
		//计算需要移动的长度
        int numMoved = size - index - 1;
        if (numMoved > 0)
        	//如果删除的不是最后一个元素,将被删除元素到最后一个元素向前移动
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        //将最后对象数组最后一个元素设置为空,在下一次gc时回收空间
        elementData[--size] = null; // clear to let GC do its work

        return oldValue;
    }

rangeCheck(int index)源码部分

//判断index是否小于数组长度,如果不是,直接抛异常
private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

3、removeAll(Collection<?> c)

该方法传入一个集合将原数组和c的交集元素删掉
removeAll(Collection<?> c)源码:

public boolean removeAll(Collection<?> c) {
		//判断c是否为空,如果为空抛异常
        Objects.requireNonNull(c);
        //进行删除
        return batchRemove(c, false);
    }

batchRemove(Collection<?> c, boolean complement)源码部分:

    private boolean batchRemove(Collection<?> c, boolean complement) {
    	//将原数组拿出来
        final Object[] elementData = this.elementData;
        //r:原数组下标,w:新数组下标
        int r = 0, w = 0;
        //删除成功标志
        boolean modified = false;
        try {
            for (; r < size; r++)
            	//complement是FALSE
            	//所以出中没有该元素就将该元素放入新数组中
            	//就是将删除的数据剔除,将其他数据依次向前提
                if (c.contains(elementData[r]) == complement)
                    elementData[w++] = elementData[r];
        } finally {
            // Preserve behavioral compatibility with AbstractCollection,
            // even if c.contains() throws.
            //正常来说r是等于size的,try有异常时,r就不等于size
            //因此,该方法是为了解决运行时异常的问题
            //将r下标后的未比对的元素,在copy新数组的时候不改变他们的位置
            if (r != size) {
            	//arraycopy(源,源的起始位置,目标,目标的起始位置,要从源移动的长度)
            	//elementData[w]这个的元素前一个元素是要操作数的最后一位元素,也就是elementData[w]是旧集合中(可能不符合)的元素。
            	//elementData[r]就是被异常停止的位置。size-r是为未比对的元素的长度
            	//该语句就是把未比对的元素,拼接在已经覆盖元素的后面。
              System.arraycopy(elementData, r,
                                 elementData, w,
                                 size - r);
                w += size - r;
            }
            //
            if (w != size) {
                // 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;
    }

小结remove

remove(Object o)方法比remove(int index)方法相比,前者需要遍历数组,而后者仅需要判断index是否合法,因此前者效率没有后者高,推荐使用后者进行删除

二、ArrayList中的获取方法

1.get(int index)

源码如下:

public E get(int index) {
		//判断index是否合法,当他大于size时直接抛出异常
        rangeCheck(index);
		//获取元素	
        return elementData(index);
    }


//elementData方法
@SuppressWarnings("unchecked")
    E elementData(int index) {
        return (E) elementData[index];
    }

总结

以上就是ArrayList中除添加方法外较为重要的源码分析,有什么问题或者建议欢迎来评论区交流。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

深藏bulu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值