一、简介
ArrayList继承自AbstractList,是List接口的变长数组实现,其底层使用一个Object数组存储元素。它实现了所有可选的列表操作,并且只能存储同一种引用类型的数据,但是包括null。除了实现List接口之外,该类还提供了操作内部用于存储列表的数组大小的方法,即数组的容量会随着数组中元素个数的增长而增长。(此类大致等同于Vector,只是它是非线程安全的。)
ArrayList特点如下:
- 动态扩容
- 非线程安全
- 允许插入的元素重复
- 插入的元素是有序的(即按照添加的先后顺序排序)
- 随机访问速度快,可以使用下标访问(底层使用数组实现)
- 插入和删除操作较慢(可能涉及到数组元素的大量移动)
二、构造函数
Method | Description |
---|---|
ArrayList() | 构造初始容量为10的空列表 |
ArrayList(int initialCapacity) | 构造具有指定初始容量的空列表 |
ArrayList(Collection<? extends E> c) | 按照集合的迭代器返回的顺序构造包含指定集合的元素的列表 |
使用方式如下:
// 构造一个初始容量为10的空列表
List<Integer> list = new ArrayList<>();
// 构造一个初始容量为16的空列表
List<Integer> list = new ArrayList<>(16);
// 在构造列表时添加元素
List<Integer> list = new ArrayList<>(){{
add(1);
add(2);
add(360);
}};
// 从已有的集合中构造新的列表
List<Integer> newList = new ArrayList<>(list);
// 注意该构造方法首先获取list对应的Object数组(如果list为空则抛出空指针异常),然后将其拷贝一份赋给newList
// 拷贝底层调用的是System.arraycopy方法,对于数组元素来说:只有数组为一维数组,并且元素为基本类型、包装类或
// String类型时,才是深拷贝;其它都属于浅拷贝;
三、常用方法
Type | Method | Description |
---|---|---|
int | size() | 返回列表中元素个数 |
boolean | isEmpty() | 如果列表为空,返回true;否则,返回false |
boolean | contains(Object o) | 判断列表中是否包含指定元素o |
int | indexOf(Object o) | 返回指定元素o在列表中的第一个下标,如果不存在则返回-1 |
int | lastIndexOf(Object o) | 返回指定元素o在列表中的最后一个下标,如果不存在则返回-1 |
E | get(int index) | 返回列表中下标为index的元素 |
E | set(int index, E element) | 将列表中下标为index的元素替换为element,返回先前位于下标index处的元素 |
boolean | add(E e) | 将元素e添加到列表末尾 |
void | add(int index, E element) | 将元素element添加到列表中下标为index的位置 |
boolean | addAll(Collection<? extends E> c) | 将集合c中的元素按其迭代器返回的顺序添加到列表末尾 |
E | remove(int index) | 删除列表中下标为index的元素,并返回该元素 |
boolean | remove(Object o) | 删除列表中第一个等于指定元素o的元素 |
void | clear() | 删除列表中的所有元素 |
T[] | toArray(T[] a) | 返回列表中元素对应引用类型的数组 |
Iterator<E> | iterator() | 返回按正确的顺序返回列表中元素的迭代器 |
添加元素:
// 构造一个初始容量为10的空列表
List<Integer> list = new ArrayList<>();
// ArrayList所有添加元素的操作都有可能会触发扩容
// 当空列表第一次调用add方法时,空列表会自动扩容为一个容量为10的新列表
list.add(1);
// 后续添加元素时只有列表满了之后才会触发扩容,新列表的容量为原来的1.5倍
list.add(2);
// [1, 2]
System.out.println(list);
// 从已有的集合中构造新的列表
List<Integer> newList = new ArrayList<>(list);
// [1, 2]
System.out.println(newList);
// 在列表指定位置添加元素,注意不能超过数组的范围,否则会抛出异常
newList.add(0, 0);
// newList.add(110, 0); java.lang.IndexOutOfBoundsException
// [0, 1, 2]
System.out.println(newList);
// 将list中的元素按其迭代器返回的顺序添加到newList的末尾
newList.addAll(list);
// [0, 1, 2, 1, 2]
System.out.println(newList);
查询元素:
// ArrayList中涉及到查询的操作都依赖equals方法,所以需要按照需求重写该方法
// true
System.out.println(newList.contains(0));
// false
System.out.println(newList.contains(100));
// 1
System.out.println(newList.indexOf(1));
// 3
System.out.println(newList.lastIndexOf(1));
遍历元素:
// 方式一,传统for循环
// 0 1 2 1 2
for (int i = 0; i < newList.size(); ++i) {
System.out.print(newList.get(i) + " ");
}
System.out.println();
// 方式二,for each
for (Integer integer : newList) {
System.out.print(integer + " ");
}
System.out.println();
// 方式三,迭代器
Iterator<Integer> iterator = newList.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
System.out.println();
修改元素:
// 将newList中的所有1改为3
for (int i = 0; i < newList.size(); ++i) {
if (newList.get(i).equals(1)) {
newList.set(i, 3);
}
}
// [0, 3, 2, 3, 2]
System.out.println(newList);
删除元素:
// ArrayList中的删除操作也依赖equals方法,所以同样需要按照需求重写该方法
// 删除下标0处的元素
newList.remove(0);
// [3, 2, 3, 2]
System.out.println(newList);
// 删除第一个元素2
newList.remove(new Integer(2));
// [3, 3, 2]
System.out.println(newList);
// 删除所有为3的元素,使用迭代器边遍历边删除
Iterator<Integer> iterator = newList.iterator();
while (iterator.hasNext()) {
Integer integer = iterator.next();
if (integer == 3) {
iterator.remove();
}
}
// 也可以使用下列方法删除
newList.removeIf(integer -> integer.equals(3));
// [2]
System.out.println(newList);
// 使用如下方式则会抛出java.util.ConcurrentModificationException
for (Integer integer : newList) {
if (integer.equals(3)) {
newList.remove(integer);
}
}
// 删除列表中的所有元素
newList.clear();
// []
System.out.println(newList);