<CoreJava> 5.3 泛型数组列表
1、为了解决运行时动态更改数组的问题,使用ArrayList类;它与数组很相似,但在增加或删除元素时具有自动调节数组容量的功能。
Employee.java:
2、ArrayList是采用类型参数的泛型类。用法:ArrayList<Class Name>
ArrayList<Employee> staff = new ArrayList<Employee>();
3、使用add方法添加元素:
staff.add(new Employee("Harry", ...));
staff.add(new Employee("Tome", ....));
如果调用add且内部数组已满时,数组列表就会自动创建一个更大容量的数组,并将小数组中的对象全部拷贝到大数组中。
4、预先分配容量大小:如果可以准确的预计数组可能存储的元素数量,可以在填充数组前调用ensureCapacity方法:
staff.ensureCapacity(100); //分配一个包含100个对象的内部数组。
这里如过调用100add,是不会重新分配空间的。
5、把初始容量传递给构造器:
ArrayList<Employee> staff = new ArrayList<Employee>(100);
警告:
分配数组列表:new ArrayList<Employee>(100);与新数组分配空间:new Employee[100];不同。
数组列表的容量与数组的大小不同:数组分配100个存储空间就表明这个数组有100个空位置可用(即用或不用那100个空间都会摆在那,不多不少);而容量为100的数组列表仅表明它拥有保存100个元素的潜力(所谓潜力就是可能超越100,可能不足100.这要实际运行中动态决定是否会重新分配容量),但是可以确定的是数组列表在完成初始化构造时不含任何元素。
数组列表的容量与数组的大小不同:数组分配100个存储空间就表明这个数组有100个空位置可用(即用或不用那100个空间都会摆在那,不多不少);而容量为100的数组列表仅表明它拥有保存100个元素的潜力(所谓潜力就是可能超越100,可能不足100.这要实际运行中动态决定是否会重新分配容量),但是可以确定的是数组列表在完成初始化构造时不含任何元素。
6、size方法将返回数组列表实际元素个数:staff.size();返回staff数组列表的当前元素个数,等价于a.length;
当确定数组列表不再增删元素时可以使用trimToSize方法。这个方法将存储空间调整为当前元素所用空间,多于的交给垃圾回收器回收。注意:一定是确定数组列表大小不变后才使用该方法,因为使用该方法后再添加新元素就要花时间再次移动存储块,时间开销较大。
5.3.1 访问数组列表元素
1、ArrayList类不是Java的一部分。而是由某些人编写且被放到标准库中的一个实用类。
2、使用get和set方法访问和改变数组元素,不能采用数组的[]语法格式。
例如:改变第i个元素:staff.set(i, harry);
等价于a[i] = harry;
警告:使用add方法添加新的元素,set方法只能改变已有元素的内容。
使用get访问数组列表的元素:Employee e = staff.get(i);
等价于:Employee e = a[i];
3、介绍个技巧,即可灵活的扩展数组,又可以方便的访问数组元素。
1)创建一个数组列表,并添加所有元素:
ArrayList<X> list = ArrayList<X>();
while (...) {
x = ...;
list.add(x);
}
2)使用toArray方法将数组列表元素拷贝到一个数组中:
x[] a = new x[list.size()];
list.toArray(a);
3)除了在尾部追加元素之外,使用带索引参数的add方法插入新元素:
int n = staff.size() / 2;
staff.add(n, e);
插入新元素后位于n后的所有元素自动向后移动,若超出容量将会重新分配存储空间。
4)删除元素:Emplouyee e = staff.remove(n);
5)使用“for each”循环对数组列表遍历:
for (Employee e : staff)
//do something with e;
4、源代码:例5-4,将Employee[]数组替换成ArrayList<Employee>。
注意变化:
不必指出数组的大小;
使用add想数组列表添加任意多的元素;
使用size代替length计算元素个数;
使用get[i]代替a[i]访问元素。
ArrayListTest.java:
- package com.vicent.corejava.arraylisttest;
- import java.util.ArrayList;
- public class ArrayListTest {
- public static void main(String[] args) {
- ArrayList<Employee> staff = new ArrayList<Employee>();
- staff.add(new Employee("Carl", 7500, 1987, 12, 15));
- staff.add(new Employee("Harry", 5000, 1989, 10, 1));
- staff.add(new Employee("Tony", 4000, 1990, 3, 15));
- for (Employee e : staff)
- e.raiseSalary(5);
- for (Employee e : staff)
- System.out.println("name: " + e.getName()
- + ", salary: " + e.getSalary()
- + ", hireDay: " + e.getHireDay());
- }
- }
Employee.java:
- package com.vicent.corejava.arraylisttest;
- import java.util.Date;
- import java.util.GregorianCalendar;
- public class Employee {
- private String name;
- private double salary;
- private Date hireDay;
- private double raise;
- public Employee(String aName, double aSalary, int year, int month, int day) {
- name = aName;
- salary = aSalary;
- GregorianCalendar calendar = new GregorianCalendar(year, month - 1, day);
- hireDay = calendar.getTime();
- }
- public String getName() {
- return name;
- }
- public double getSalary() {
- return salary;
- }
- public Date getHireDay() {
- return hireDay;
- }
- public void raiseSalary(double byPercent) {
- raise = salary * byPercent / 100;
- salary += raise;
- }
- }
运行结果:
name: Carl, salary: 7875.0, hireDay: Tue Dec 15 00:00:00 CST 1987
name: Harry, salary: 5250.0, hireDay: Sun Oct 01 00:00:00 CST 1989
name: Tony, salary: 4200.0, hireDay: Thu Mar 15 00:00:00 CST 1990