在许多程序设计语言中,特别是C++,必须在编译时就确定数组的大小,一旦确定了数组的大小就很难改变。程序员对此十分反感,用为这样将迫使程序员做一些不情愿的折中。列如,在一个部门中有多少个雇员呢?肯定不会超过100个。一旦出现一个有150个雇员的大型部门呢?原以为那些仅有10个雇员的部门浪费90个雇员占据的内存空间吗?
Java中情况就好多了,允许在运行时确定数组大小。担任然没有完全解决在运行时动态更改数组的问题。

  1. int actucalSize = ...;
  2. int[] arrays = new Int[actucalSize];

ArrayList类

在Java中,解决这个问题最简单的方法即使使用 ArrayList类。它使用起来有点像数组,但在添加或删除元素时,具有自动调节数组容量的功能,而不需要为此编写任何代码。
ArrayList是一个采用类型参数的泛型类,为了指定数组列表保存的数据类型,需要用一对尖括号将类名括起来加在后面 ArrayList<Type>

声名数组列表

下面声名了一个保存自定义类 User对象 的数组列表
注意: 尖括号中的带参数类型不允许使用基本数据类型 ,请使用它们的 包装器类

  1. /* 保存自定义类User对象的数组列表 */
  2. ArrayList<User> userLists = new ArrayList<>();

使用add / remove 添加/删除元素

/ 向数组列表中间添加元素 /
userLists.add(2, new User(“addUser”))

  1. /* 向数组列表中添加对象 */
  2. userLists.add(new User("liu"));
  3. userLists.add(new User("si"));
  4. userLists.add(new User("yuan"));
  5. /* 向数组列表中间添加元素 */
  6. userLists.add(2, new User("addUser"));
  7. /* 向数组列表中间删除元素 */
  8. User removeUser = userLists.remove(n);

数组列表管理着对象引用的一个内部数组,如果调用add()方法且内部数组已经装满,数组列表将自动创建一个更大的数组,并将所有数据拷贝到较大的数组中。

ensureCapacity 方法

如果已经清楚或能够估计数组可能存储的元素数量,就可以在填充数组之前调用ensureCapacity 方法。

userLists.ensureCapacity(100)

这个方法将分配一个包含100个对象的内部数组。然后调用100此add,而不用重新分配空间。

创建时确定初始容量

  1. ArrayList<User> userLists = new ArrayList<>(100);

数组列表容量new ArrayList<int>(100) 与数组大小 new int[100] 有一个非常重要的区别。如果为数组分配100个元素的储存空间,那数组就有100个空位置可以使用。而容量为100个元素的数组列表只是拥有保存100个元素的潜力,(实际上,重新分配空间的话,将会超过100),但是在最初、甚至完成初始化构造之后,数组列表根本就不含有任何元素。

size方法

size方法将返回数组列表中包含的实际元素个数,等价与数组的 length。

  1. userLists.size(); // -> 3

一旦能够确定数组列表大小不会发生变化,就可以调用 trimToSize 方法,这个方法将存储区域大小调整为当前元素数量需要的存储空间数目。垃圾回收器将回收多余的存储空间。

访问数组列表元素

数组列表自动扩容的便利增加了访问元素语法的复杂程度。其原因是ArrayList类并不是Java程序设计语言的一部分;它只是一个由某些人编写并放在标准库中的实用类。

  • 使用 get 访问元素

    1. userLists.get(i);
  • 使用 set 设置第 i 个元素

    1. userLists.set(i, new User("addUser"));

创建技巧

该方法既可以灵活的扩展数组,又可以方便的访问数组元素

  1. /* 创建一个数组列表,并添加所有元素 */
  2. ArrayList<User> userLists = new ArrayList<>();
  3. while(...)
  4. {
  5. User user = ...;
  6. userLists.add(user);
  7. }
  8. /* 使用 toArray 方法将数组元素拷贝到一个数组中 */
  9. User[] users = new User[userLists.size()];
  10. userLists.toArray(users);

对数组实施插入和删除操作效率比较低,对小型数组来说,这一点不用担心。但如果数组存储的元素较多,又经常需要在中间位置插入/删除元素,就应该考虑使用链表。

遍历数组列表

  1. for(User u : userLists)
  2. {
  3. // do something with u
  4. }