前言:顺序表是线性表的一种,它是较于数组更加灵活的一种储存方式。线性表通常是逻辑上是连续的一条直线,但在物理上不是连续的。java中已经实现好了一个顺序表,搭配泛型可以支持各种类型的使用,下面就来介绍该如何使用。
ArrayList简介
在集合框架中,ArrayList是一个普通的类,实现了List接口。
ArrayList是以泛型方式实现的,使用必须先实例化。底层逻辑是一段连续的空间,可以支持动态扩容,是一个动态类型顺序表。
和Vector不同,ArrayList不是线程安全,在单线程可以使用,多线程得选择Vector或CopyOnWriteArrayList。
ArrayList内部实现
ArrayList内部:
可以看到,list内部有几个重要的成员变量:
ArrayList扩容机制
在使用add来进行扩容时,我们可以看到是由上述图来实现1.5倍的扩容,在插入元素的时候会自动检测扩容。
ArrayList的构造方法
ArrayList(int initialCapacity)
指定顺序表初始容量
给定一个形参,他会初始化一个指定初始化容量大小的类型数组,用来存放数据。
看看内部实现:
这个非常好理解,可以看见,要是给定的大小合法,则会直接创立一个新对象数组来赋给ArrayList的成员变量elementData(ArrayList操作的时候都是使用该数组)若是给定大小为零,则直接传一个ArrayList的成员变量的空数组。若是给定大小小于零,则直接报错。
ArrayList(Collection <? extends E>c)
利用其他Collection来构建ArrayList
我们可以看到,使用这个构造方法可以直接初始化构建一个顺序表。
内部实现:
这里的“?”代表通配符,整体意思就是:
1.<>里面只要实现了Collection接口都是可以传参的,如:
上述的图片中可以看到List实现了Collection接口,所有实现了Collection接口的都可以传入
2.这里的E代表着通配符的上界,意味着要么是E要么是c(E的子类)
经上述的细节之后,才能真正初始化构建一个带有顺序表的顺序表。
ArrayList()
无参构造
直接创立的无参顺序表
可以看见,内部只有简简单单的一个赋值,赋的是空的数组。
但是,我们可以使用add方法来初始化一下顺序表。使用add方法时(如上述ArrayList扩容机制讲到),采用的是扩容的方法来帮助这个空表初始化,通常默认为10,也就实现了该顺序表为空的状态。
ArrayList常见操作
如图:
这里只演示比较容易出错的的方法:
1.remove(int ···) 和 remove(Object ···)
第一个通俗易懂,就是删除下标,但是第二个就容易和第一个混淆。比如在Integer类型顺序表中,系统会无法分辨传入的是下标还是元素:
所以第二个remove通常是这样写:
2.subList(int···,int···)
这个是截取部分内容(前闭后开区间),但注意的是,截取后并不会建立新的对象,只是拿到了截取到部分的地址而已:
ArrayList遍历方法
有三种方法可以遍历:
for - i:
for - each:
迭代器(iterator ,listIterator):
俩个迭代器的区别在于一个需要传入元素个数参数,一个不用。一个可以实现从后往前迭代,一个不能。