arraylist删除指定元素_Java集合框架:ArrayList,探讨了解,有不同理解可以在评论留言...

前言

这个分类中,将会写写Java中的集合。集合是Java中非常重要而且基础的内容,因为任何数据必不可少的就是该数据是如何存储的,集合的作用就是以一定的方式组织、存储数据。这里写的集合,一部分是比较常见的、一部分是不常用但是我个人平时见到过的,一些比较相似的集合(比如HashMap和Hashtable)就只讲一个,突出它们之间的区别即可。

最后,要指出一点,对于集合,我认为关注的点主要有四点:

1、是否允许空

2、是否允许重复数据

3、是否有序,有序的意思是读取数据的顺序和存放数据的顺序是否一致

4、是否线程安全

ArrayList

ArrayList是最常见以及每个Java开发者最熟悉的集合类了,顾名思义,ArrayList就是一个以数组形式实现的集合,以一张表格来看一下ArrayList里面有哪些基本的元素:

元 素作 用private transient Object[] elementData;ArrayList是基于数组的一个实现,elementData就是底层的数组private int size;ArrayList里面元素的个数,这里要注意一下,size是按照调用add、remove方法的次数进行自增或者自减的,所以add了一个null进入ArrayList,size也会加1

四个关注点在ArrayList上的答案

以后每篇文章在讲解代码前,都会先对于一个集合关注的四个点以表格形式做一个解答:

关 注 点结 论ArrayList是否允许空允许ArrayList是否允许重复数据允许ArrayList是否有序有序ArrayList是否线程安全非线程安全

添加元素

有这么一段代码:

public static void main(String[] args){ List list = new ArrayList(); list.add("000"); list.add("111");}

看下底层会做什么,进入add方法的源码来看一下:

 public boolean add(E e) { ensureCapacity(size + 1); // Increments modCount!! elementData[size++] = e; return true; }

先不去管第2行的ensureCapacity方法,这个方法是扩容用的,底层实际上在调用add方法的时候只是给elementData的某个位置添加了一个数据而已,用一张图表示的话是这样的:

1b6bf84427935ff397ff4bbf9a436ec3.png

多说一句,我这么画图有一定的误导性。elementData中存储的应该是堆内存中元素的引用,而不是实际的元素,这么画给人一种感觉就是说elementData数组里面存放的就是实际的元素,这是不太严谨的。不过这么画主要是为了方便起见,只要知道这个问题就好了。

扩容

我们看一下,构造ArrayList的时候,默认的底层数组大小是10:

public ArrayList() {this(10);}

那么有一个问题来了,底层数组的大小不够了怎么办?答案就是扩容,这也就是为什么一直说ArrayList的底层是基于动态数组实现的原因,动态数组的意思就是指底层的数组大小并不是固定的,而是根据添加的元素大小进行一个判断,不够的话就动态扩容,扩容的代码就在ensureCapacity里面:

public void ensureCapacity(int minCapacity) {modCount++;int oldCapacity = elementData.length;if (minCapacity > oldCapacity) { Object oldData[] = elementData; int newCapacity = (oldCapacity * 3)/2 + 1; if (newCapacity < minCapacity) newCapacity = minCapacity; // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity);}}

看到扩容的时候把元素组大小先乘以3,再除以2,最后加1。可能有些人要问为什么?我们可以想:

1、如果一次性扩容扩得太大,必然造成内存空间的浪费

2、如果一次性扩容扩得不够,那么下一次扩容的操作必然比较快地会到来,这会降低程序运行效率,要知道扩容还是比较耗费性能的一个操作

所以扩容扩多少,是JDK开发人员在时间、空间上做的一个权衡,提供出来的一个比较合理的数值。最后调用到的是Arrays的copyOf方法,将元素组里面的内容复制到新的数组里面去:

public static T[] copyOf(U[] original, int newLength, Class extends T[]> newType) {

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;

}

用一张图来表示就是这样的:

ff626cbf8533423018fe32e640fe3c21.png

删除元素

接着我们看一下删除的操作。ArrayList支持两种删除方式:

1、按照下标删除

2、按照元素删除,这会删除ArrayList中与指定要删除的元素匹配的第一个元素

对于ArrayList来说,这两种删除的方法差不多,都是调用的下面一段代码:

int numMoved = size - index - 1;if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved);elementData[--size] = null; // Let gc do its work

其实做的事情就是两件:

1、把指定元素后面位置的所有元素,利用System.arraycopy方法整体向前移动一个位置

2、最后一个位置的元素指定为null,这样让gc可以去回收它

比方说有这么一段代码:

public static void main(String[] args){ List list = new ArrayList(); list.add("111"); list.add("222"); list.add("333"); list.add("444"); list.add("555"); list.add("666"); list.add("777"); list.add("888"); list.remove("333");}

用图表示是这样的:

747b00f7eccc17bb640d89eef0d4c0d0.png

插入元素

看一下ArrayList的插入操作,插入操作调用的也是add方法,比如:

 1 public static void main(String[] args) 2 { 3 List list = new ArrayList(); 4 list.add("111"); 5 list.add("222"); 6 list.add("333"); 7 list.add("444"); 8 list.add("555"); 9 list.add("666");10 list.add("777");11 list.add("888");12 list.add(2, "000");13 System.out.println(list);14 }

有一个地方不要搞错了,第12行的add方法的意思是,往第几个元素后面插入一个元素,像第12行就是往第二个元素后面插入一个000。看一下运行结果也证明了这一点:

[111, 222, 000, 333, 444, 555, 666, 777, 888]

还是看一下插入的时候做了什么

 1 public void add(int index, E element) { 2 if (index > size || index < 0) 3 throw new IndexOutOfBoundsException( 4 "Index: "+index+
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值