大家好,今天我们介绍一下java中常用的集合类型。
首先,我们先看一下java中集合类型的结构。
以上是集合的继承关系图,通常我们使用的比较多的是 Set , List , Map以及其衍生的子类和接口实现类。
首先给大家介绍一下List,List本身是一个接口类,它向它的实现类定义了一系列的接口函数。
在List类后跟了一个标记,表示对于List来说,是可以指定类型的,比如List,代表list保存的数据类型为String字符串,又比如List,代表list保存的数据类型为封装int
他代表的是有序的,可重复的一个集合体,为了研究他的具体逻辑,我们从ArrayList的源码开始对应List接口所规范的接口函数。
1.add(E e);
add函数提供了向ArrayList对象添加一个数据的功能,具体源码如下
可以看到ArrayList类实现了List接口中的add函数,我们来看看他是如何做的。
首先源码462行中,调用了函数ensureCapacityInternal,这个函数的主要作用是用于判断当前集合内保存数据的数组(what?)的长度是否满足继续添加,如果不满足的话就需要进行扩容,具体实现代码如下
我们发现,ArrayList对象做add操作时似乎是将数据保存在了数组中,向上翻阅源码
原来ArrayList对象对于数据的保存是确实是放在了数组里,那么从这里我们至少可以了解到,对于ArrayList来说,最多保存的数据量也就是int数字的最大值。而由于保存的内容是放在数组里的,于是,对于ArrayList,保存的数据是有顺序性的(数组用标识来表示顺序)。
接着看源码的463行,add函数将传入的参数加入到了数组中,放入的位置是size++。那么size又代表什么呢,我们继续查看源码
上面的注释已经很明确的告诉我们,size代表的是当前的arraylist对象的长度,由于int类型的默认值为0,所以,当我们第一次调用add函数,执行的代码实际上是
elementData[0] = e;
由于执行了size++,所以,当这一次add操作完成时,size的值由0 增长 为了1,那么下一次再执行add操作时,传入的参数就放到了数组的标识1的位置。
2.size();
根据上面的分析,我们很容易就可以知道,这个函数得到的结果是当前ArrayList对象中数据数组所保存的数据数量(不是数组长度)
了解了这些内容,那么其他的函数就比较好理解了。
3.isEmpty()
判断当前对象的数据量是否是0
4.indexOf(Object o)
通过正向遍历,获得指定值第一次出现的标识值
5.lastIndexOf(Object o)
通过逆向遍历,获得指定值最后一次出现的标识值
6.contains(Object o)
调用indexof函数确定指定的值时否存在于当前数组中
7.get(int index)
rangeCheck函数用于确定传入的标识是在数组的允许标识范围内,如果没有满足,则会抛出异常,对于异常,在后续章节会为大家介绍。接着,调用elementData函数返回数组中指定标识的数据
8.remove(int index) / remove(Object o)
remove函数删除指定标识的数据/remove函数删除指定内容的数据
remove函数稍微复杂一些,首先验证了标识的正确性,接着将指定标识位置的数据暂存在oldValue变量中,接着通过系统提供的arraycopy函数将当前数组中从标识的位置开始,一直都尾部的数据进行重新覆盖,接着,size自减,并将数组的最后一位设置为null。
上图为各位演示ArrayList的使用示例
运行结果为
ps:对于源码中的一些函数如果不能理解,可以尝试自己去找找资料,或者给 进击留言,有时间的时候会给大家回复的哈。
通过add和remove函数,我们了解到,ArrayList本身实现基于数组,而又由于数组本身的特性(定义长度后不可更改长度,只能重新声明),ArrayList在增加,删除时,系统资源开销会比较大,所以,如果在以后有需要频繁的增删操作的集合结构,应该尽量避免使用ArrayList。
以上就是ArrayList类中一些常用的函数,除了这些之外,还有很多没有介绍到的函数,大家可以自己去了解一下。