本篇文章将对ArrayList类进行讲解
一、ArrayList类介绍
上篇文章我们对顺序表的增删查改等方法进行了模拟实现,实际上Java提供了ArrayList类,而在这个类中就包含了顺序表的一系列方法,这样在用顺序表解决问题时就不用每次都去实现它的方法了
再ArrayList类中有下面几个字段:
上述字段会在下面的解释中进行讲解
二、ArrayList的构造方法
ArrayList的构造方法一共有三种
2.1 第一种构造方法
上述代码中,先定义了数组EMPTY_ELEMENTDATA,该数组为空,之后又定义了数组elementData,接下来红色框部分的就是构造方法,该方法有一个参数initialCapacity(即顺序表的初始容量),当initialCapacity > 0时,为elementData分配了长度为initialCapacity大小的空间,当initialCapacity =0时,将elementData赋值为EMPTY_ELEMENTDATA,也就是此时elementData为空数组,即顺序表现在为空,若initialCapacity为负数,则抛出异常
总结:该构造方法就是给顺序表分配空间的
ArrayList arrayList = new ArrayList(5); //此时顺序表的长度为5arrayList.add(1);arrayList.add(2);arrayList.add(3);
2.2 第二种构造方法
可以看到此时elementData为一个空数组,那么看下面的代码
ArrayList arrayList = new ArrayList();arrayList.add(1);arrayList.add(2);arrayList.add(3);
构造方法并没有给顺序表分配空间,为什么此代码编译运行都没有问题?下面通过源码进行解释,首先不带参的构造方法确实没有给顺序表分配空间,那么没有报错的原因只可能是在add方法上
add方法中调用了ensureCapacityInternal方法:
在该方法中调用了ensureExplicitCapacity方法,其参数为calculateCapacity方法的返回值,该方法的参数分别为elementData数组和minCapacity先看calculateCapacity方法:
上述代码中的DEFAULT_CAPACITY是默认容量:10,minCapacity为1,所以这里将10作为该方法的返回值并作为ensureExplicitCapacity的参数,再去看ensureExplicitCapacity方法:
接下来看grow方法:
总结:
1.对于空的顺序表,第一个add方法会进行扩容,将顺序表的扩容为默认容量10
2.add方法的扩容是按照1.5倍扩容的
2.3 第三种构造方法
该构造方法的参数部分:
Collection
三、ArrayList的一些方法
ArrayList类提供的方法大部分和上篇文章中模拟实现的方法一致,这里讲解一些没有模拟实现的方法:
1. boolean addAll(Collection c)
该方法为将一个顺序表的所有元素尾插到另一个顺序表:
public static void main(String[] args) {ArrayList arrayList = new ArrayList();arrayList.add(1);arrayList.add(2);ArrayList list = new ArrayList();list.add(3);list.addAll(arrayList);System.out.println(list); //结果为 [3, 1, 2]}
2. E remove(int index)
删除index位置的元素:
public static void main(String[] args) {ArrayList arrayList = new ArrayList();arrayList.add(1);arrayList.add(2);arrayList.remove(0);System.out.println(arrayList); //结果为 [2]}
3. List subList(int fromIndex, int toIndex)
以左闭右开的区间截取顺序表中从fromIndex到toIndex的元素,注意:这里的截取并不是指向一个新的对象,它依然指向原来的对象
public static void main(String[] args) {ArrayList arrayList = new ArrayList();arrayList.add(1);arrayList.add(2);arrayList.add(3);List list = arrayList.subList(0, 2);//list依然指向原来的对象System.out.println(list); //结果为 [1, 2]list.set(0, 100);System.out.println(list); //[100, 2]System.out.println(arrayList); //[100, 1, 2]}
四、ArrayList的遍历
先创建一个顺序表:
ArrayList arrayList = new ArrayList();arrayList.add(1);arrayList.add(2);arrayList.add(3);
4.1 for循环
for (int i = 0; i < arrayList.size(); i++) {System.out.print(arrayList.get(i) +" ");}
4.2 for-each循环
for(Integer x : arrayList) { //:左边为顺序表中元素的类型+变量System.out.print(x +" ");}
4.3 迭代器
1.Iterator接口中iterator()方法
Iterator it = arrayList.iterator();while(it.hasNext()) { System.out.print(it.next() +" ");//判断是否有下一个元素,如果有则打印下一个元素,并将it指向下一个元素}
2.ListIterator接口中listIterator()方法
ListIterator接口继承了Iterator接口,也可以作为迭代器遍历ArrayList
ListIterator it1 = arrayList.listIterator();while(it1.hasNext()) {System.out.print(it1.next() +" ");}
3.利用迭代器从后往前打印
ListIterator it2 = arrayList.listIterator(arrayList.size());//这里要将顺序表的长度作为参数传过去while(it2.hasPrevious()) {System.out.print(it2.previous() +" ");//判断是否有前一个元素,如果有则打印前一个元素,并将it指向前一个元素}
本篇文章到此结束,下篇文章会对链表相关知识进行讲解