1. 程式人生 > 實用技巧 >陣列列表(ArrayList)

陣列列表(ArrayList)

2020-10-20        [email protected]        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);
}