2020-10-20 longzqa@163.com stronglzq
【摘要】针对数组容量固定无法扩展的问题,引入数组列表(ArrayList)。主要对数组列表的声明及基本操作等内容进行介绍,基本操作包括增加元素、插入元素、删除元素以及元素的访问与修改。
- 为什么要引入数组列表(ArrayList)
- 数组列表容量为什么能变动
- 如何声明数组列表
- 数组列表的增加、插入、删除、修改、访问操作
- 数组列表的缺陷
- 如何灵活的扩展数组,又能方便的访问元素
- 如何降低数组列表的内存消耗 -- 预设列表容量
为什么要引入数组列表(ArrayList)
数组在创建后容量固定,而实际解决问题的过程中,元素的数量是变动的,此时采用数组来存储数据难以满足业务需求,因此引入数组列表。
数组列表容量为什么能变动
在创建数组时,需确定数组长度,此时数组中产生一个个“萝卜坑”(有初始值,若为int类元素,初始值为0),增加元素即为往“萝卜坑”中放入“萝卜”;数组列表可在声明时预估容量,或不预估容量,当不预估容量,或者元素超过预估容量时,若增加一个元素,则会自动申请一个新的数组,将原先数组列表的内容复制到新数组中,并在末端放入新元素。
如何声明数组列表
数组列表是具有类型参数(type parameter)的泛型类(genetic class),故需要在声明数组列表时,指明元素类型,语法为ArrayList<element type>。数组列表的声明语法有三种:
ArrayList<element type> name = new ArrayList<element type>();-
ArrayList<element type> name = new ArrayList<>();,相对于第一种声明方法,省略了等号右侧数组列表的元素类型; -
var name = new ArrayList<element type>();,使用var则一定不能省略等号右侧数组列表的元素类型。
public class Person{
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
}
public class ArrayListTest{
// 用数组列表来存储Person数据
var person = new ArrayList<Person>();
// ArrayList<Person> person = new ArrayList<Person>();
// ArrayList<Person> person = new ArrayList<>();
person.add(new Person("Peter", 20));
person.add(new Person("Tom", 23));
person.add(new Person("Lucy", 26));
}
数组列表的增加、插入、删除、修改、访问
(1)数组列表的增加为在列表末端增加元素,使用add()方法;(2)对位置i的元素修改为e,语句为set(i, e);(3)访问位置i的元素,语句为get(i);(4)在位置i,插入元素e,则原先位置i及之后的元素均向后移一位,语句为add(i, e);(5)删除位置i的元素,语句为remove(i)。
注:数组列表的插入、删除效率低。
public ArrayListTest{
// 用数组列表来存储Person数据
var person = new ArrayList<Person>();
// ArrayList<Person> person = new ArrayList<Person>();
// ArrayList<Person> person = new ArrayList<>();
person.add(new Person("Peter", 20));
person.add(new Person("Tom", 23));
person.add(new Person("Lucy", 26));
// 修改元素
person.set(1, new Person("Peter Long", 25));
// 插入元素
person.add(2, new Person("Jack", 30));
// 删除元素
person.remove(0);
// 访问元素
person.get(1);
}
数组列表的缺陷
使用数组列表存在两个缺陷,(1)无法直接通过元素下标来访问元素,不方便;(2)数组列表由于每变动一个元素,均需要重新申请一个新的数组来存放,对内存消耗大;(3)数组列表元素的插入、删除效率低,解决方案为采用链表的数据类型;
如何既灵活的扩展数组,又能方便的访问数组元素?
数组无法灵活的扩展,故引入了数组列表,但数组列表元素访问繁琐,针对各自的问题,有一解决方法:(1)创建一个数组列表,并填充元素;(2)创建一个数组,数组大小为数组列表实际元素的数量;(3)使用toArray方法,将数组列表的元素复制到该数组中。
public class ArrayListTest{
// 用数组列表来存储Person数据
var person = new ArrayList<Person>();
// ArrayList<Person> person = new ArrayList<Person>();
// ArrayList<Person> person = new ArrayList<>();
person.add(new Person("Peter", 20));
person.add(new Person("Tom", 23));
person.add(new Person("Lucy", 26));
// 创建一个数组,大小为数组列表的大小
Person[] personArray = new Person[person.size()];
// 将数组列表的元素复制到数组中
person.toArray(personArray);
}
注:数组列表的size()方法返回数组列表实际元素的数量,而数组的size()方法返回数组容量。
如何降低数组列表的内存消耗?-- 预设列表容量
针对数组列表内存消耗大的问题,可以预设一个列表容量,在元素数量不超过预设容量时,元素的增加不需要重新分配空间。预设列表容量有两种方式:(1)在构造数组列表时,确定列表容量;(2)使用数组列表的ensureCapcity()方法。
public class ArrayListTest{
// 预设数组列表的容量为100
var person = new ArrayList<Person>(100);
// 或 var person = new ArrayList<Person>(); person.ensureCapcity(100);
}